力扣—1015.可被k整除的最小整数

题意理解

题目描述及示例如图:
力扣—1015.可被k整除的最小整数_第1张图片
其中红色框框便是对要找的整数n的要求:①能够被k整除,即n%k=0;②仅包含数字[1],即111,111111等这样包括了多个(或一个)1的整数,可以将n初始化为1,之后n=n*10+1,达到增加1的数量;③满足①和②的最小正整数,即在有解的前提下,按照n=n*10+1增加n的长度找到的第一个能够整k的整数。

解法

  1. 首先如果数字k很大,那么直接寻找n,n可能会很大,n=n*10+1增加n的长度可能使得n超出in类型的最大值;
    我们考虑用余数r来代替n:
    假设:n%k = r (即:n = k*i+r ,i≥1)
    那么:n’%k = (n*10+1)%k = (k*i*10 +r*10 +1) %k = (r*10+1)%k
    因此可以用 r*10+1代替n*10+1
    并且因需要求出n的长度,不需要记录n,因此用余数r来代替n;

  2. 能够直观的知道k是否有解?
    n的末尾是1,如果k%2=0或者k%5=0,存在n%k=0,n的末尾肯定不能是1,因此如果k%2=0或k%5=0,不存在题意要求的n,直接返回-1;

  3. 除2中提到的之外的k一定有解吗?
    因为用余数r代替了n,余数的范围是0~k-1,如果存在ri=ni%k=nj%k=rj≠0,即两个数除k的余数是一样的且余数不为0,那么会重复之前的循环,即无解,死循环。
    上述式子可以表示成 (ni-nj)%k=0,其中ni-nj=11…1100…00
    如果k不是2的倍数也不是5的倍数,即k和10是互质的,那么11…1100…00%k≠0,即有解。
    (满足的情况是只有0个0,即11…11%k=0,也正好说明有解)

代码

int smallestRepunitDivByK(int k) {
   //如果是2或者5的倍数无解直接返回-1
	if(k%2==0||k%5==0) return -1;
	//n=1,初始长度len=1	
    int len=1;
    //r表示余数,初始n=1,r=n%k=1%k
    int r=1%k;
    //只要余数r不为0,就没有找到可以整除k的数,继续循环
    while(r){
    	len++;
    	//末尾增加1
     	r=r*10+1;
     	//求余
        r=r%k;          
    }
	return len;
}

你可能感兴趣的:(力扣刷题,leetcode,算法,数据结构)