【LeetCode 每日一题】1015. 可被 K 整除的最小整数

195 阅读2分钟

1015. 可被 K 整除的最小整数

难度:中等

时间:2023/05/11


给定正整数 k ,你需要找出可以被 k 整除的、仅包含数字 **1** 的最 正整数 n 的长度。

返回 n 的长度。如果不存在这样的 n ,就返回-1。

注意: n 不符合 64 位带符号整数。

示例 1:

输入:k = 1
输出:1
解释:最小的答案是 n = 1,其长度为 1

示例 2:

输入:k = 2
输出:-1
解释:不存在可被 2 整除的正整数 n 。

示例 3:

输入:k = 3
输出:3
解释:最小的答案是 n = 111,其长度为 3

提示:

  • 1 <= k <= 10^5

思路与算法

从小到大遍历所有的可能的只包含1的数值,对于每一个数值,计算其关于k的余数。

如果余数为0,那么该数就是满足条件的最小数值,返回其长度即可。

如果余数不为0,则将该余数存入哈希表中,如果在之后的遍历中又出现该余数,说明遍历将跳入一个循环,不存在满足条件的数值,所以直接返回-1即可。

返回的n是1, 11, 111, 1111....如果开始时n=1,那么后续可以表示为n * 10 + 1,现在要求n % k == 0,那么就是相当于求(n * 10 +1 ) % k == 0,等价于 (n * 10 % k + 1) % k == 0,由此可知当且仅当k为2或者5时n%k永远等于1,其他情况下一定存在解。

直接x10+1必然会溢出,考虑到 (Ax10+1)%K = (A%K x10+1)%K,遂采用取余的方法来替代原数直接乘。 K为偶数或者末位为5的时候得不出1,遂剔除。

func smallestRepunitDivByK(k int) int {
    if k%2 == 0 || k%5 == 0 {
        return -1
    }
    cnt, cur := 1, 1
    for {
        if cur%k == 0 {
            return cnt
        }
        cur = (cur*10 + 1) % k
        cnt++
    }
}
class Solution {
    public int smallestRepunitDivByK(int K) {
​
        if (K%2==0||K%5==0)return -1;
        int remainder = 0;
        int length = 1;
        while (true){
            remainder = (remainder*10+1)%K;
            if (remainder==0)break;
            length++;
        }
        return length;
​
    }
}
​