从零开始学习c++,每天起码做一道leetcode题目,在此记录,希望最后能够有所收获!
一、题目描述
给定正整数 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 <= 105
二、思路分析
本题不能直接列举n, n 只能由 1 组成,虽然可以通过公式 n = n * 10 + 1 不断地得到下一个 n ,直至 n 对 k 取余 为 0,最后返回 n 的长度即可,然而单纯的使用这种暴力破解的方法,n 会变得相当大,计算异常耗时,最终导致时间超时,因此需要考虑从 余数 入手,因为 余数 永远不会大于 k !
这就涉及到了两个关于取模的公式:
根据这两个公式,可以对通用的公式n(m)=n(m-1)*10+1进行推导,依此我们就可以得到余数r间的关系:
同时可以优化一下,k若为偶数,则k的倍数必为偶数,个位数上不可能为1;同样的k若为5的倍数,则个位数上不是0就是5,不可能是1
三、AC代码
class Solution {
public:
int smallestRepunitDivByK(int k) {
int ans=1;
int t=ans%k;
unordered_set<int>record;
while(t!=0){
t=(t*10+1)%k;
if(!record.count(t)){
record.insert(t);
}
else{
break;
}
}
if(t==0){
return record.size()+1;
}
return -1;
}
};
四、总结
主要需要知道取余的那两条规则。