/*
思路:(这里不仅仅局限于1,其他数字也是相通的)
找规律,当计算右数第 i 位包含的 X 的个数时:
取第 i 位左边(高位)的数字,乘以 10 i−1 ,得到基础值 a 。
取第 i 位数字,计算修正值:
如果大于 X,则结果为 a+ 10 i−1 。
如果小于 X,则结果为 a 。
如果等 X,则取第 i 位右边(低位)数字,设为 b ,最后结果为 a+b+1 。
相应的代码非常简单,效率也非常高,时间复杂度只有 O( log 10 n) 。
*/
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
int res = 0,high = n,low,curr,temp,i = 1;
while(high){
high = n/(int)pow(10,i);
temp = n%(int)pow(10,i);
curr = temp/(int)pow(10,i-1);
low = temp%(int)pow(10,i-1);
if(curr<1)
res += high*(int)pow(10,i-1);
if(curr>1)
res += (high+1)*(int)pow(10,i-1);
if(curr==1)
res += (high*(int)pow(10,i-1)+low+1);
i++;
}
return res;
}
};