问题:
难度:medium
说明:
求一个数字 N,N 是由十进制的 1 组成(意思是 1, 11, 111, 1111 都是十进制的数字,不是二进制),然后 N 能够被 K 整除(被整除,就是 N % K 余数为 0),返回一个值最小的 N。
题目连接:https://leetcode.com/problems/smallest-integer-divisible-by-k/submissions/
输入案例:
Example 1:
Input: K = 1
Output: 1
Explanation: The smallest answer is N = 1, which has length 1.
Example 2:
Input: K = 2
Output: -1
Explanation: There is no such positive integer N divisible by 2.
Example 3:
Input: K = 3
Output: 3
Explanation: The smallest answer is N = 111, which has length 3.
我的代码:
其实题目很让人迷惑,说 N 由 1 组成,可能想不通究竟是什么 1,然后 N 被 K整除,意思是 N 除以 K 没有余数,而且 N 是 1, 11 ,111 这样的 十进制数字。
比较数学的题目,看了好久才明白过来,根据公式
mod( i ) = N ( i ) % K
mod( i + 1) = N( i + 1) % K
N( i + 1 ) = N( i ) * 10 + 1
因此得出:mod( i + 1 ) = ( mod( i ) * 10 + 1 ) % K,是分治法。
然后因为,如果是没有能被 K 整除的 N 的数字时候,mod( i ) 会出现一个循环的规则,是需要判断余数是否出现循环就行了,做个 map 缓存。
(不要往 for 循环乱丢东西啊!)
用 map 缓存
class Solution {
private static boolean[] map = new boolean[50000];
public int smallestRepunitDivByK(int K) {
if((K & 1) != 0) {
Arrays.fill(map, false);
for(int mod = 1 % K, times = 1;!map[mod];map[mod] = true, mod = (mod * 10 + 1) % K, ++ times)
if(mod == 0) return times;
}
return -1;
}
}
如果优化一下,就是当 times <= K 的时候都没办法得出 0 余数,那肯定也没救,因为 map[].length == K,如果已经是 K + 1 肯定是出现重复了。
class Solution {
public int smallestRepunitDivByK(int K) {
if((K & 1) != 0)
for(int mod = 1 % K, times = 1;times <= K;mod = (mod * 10 + 1) % K, ++ times)
if(mod == 0) return times;
return -1;
}
}