题目:输入一个整数n,求从1到n这个n个整数的十进制表示中1(K=1)出现的次数,例如输入15, 则1到15中的整数中包含1的数字有1,10,11,12,13,14,15,共7次。
分析:这道题目首先第一个思路就是对1到15的整数,挨个求其中的1的个数,对n个数,每个数操作logn次,则复杂度为O(n*logn),较好的方法应该为根据数字的规律进行计算,从高位(左到右),异或从低位开始均可。先贴代码:
int countDigitOne(int n,int K) {
int numLeft = n, curDigit, curLevel = 1, residual, res = 0;
while(numLeft>0)
{
residual = (n % curLevel) + 1; //包含0,1,2,...,k
curDigit = numLeft % 10;
numLeft /= 10;
if(curDigit>=K) res += curDigit>K?curLevel:residual;
res += curLevel* numLeft;
curLevel *=10;
}
return res;
}
int main()
{
int result;
result=countDigitOne(325);
cout<<result<<endl;
return 0;
}
上述算法主要的思路:针对整数n,从低位开始,获得其个位数字,即curDigit,其消去个位后的整数numleft,curLevel是当前数字的权重,即(1,10,100,1000,...),较难理解的是residual这个参数,当一个数字与K相等时,则只能算该数字对应的位更低一位的数字。比如:对应n=325,curDigit=2, curLevel=10, numleft=3, K=2, 因为curDigit=K,没有curLevel个K,只有20,21,...,25共6个K值。
参考:
https://leetcode.com/discuss/44299/my-c-solution-just-scan-each-digit-from-right-to-left