题干:
给定一个整数 n
,计算所有小于等于 n
的非负整数中数字 1
出现的个数。
原理:
个位出现1的规律:每增加10个数,产生一个1,总数=n/10+1+修正值
十位出现1的规律:每增加100个数,产生10个1,总数=(n/100)*10+10+修正值
百位出现1的规律:每增加1000个数,产生100个1,总数=(n/1000)*100 + 100 + 修正值
其他同理。
修正值:考虑十位时,
例如100<=n<110,(n/100)*10+10=20,实际上只有1*10个另外十个考虑的是110~119,所以修正值为10,
例如110<=n<119,(n/100)*10+10=20,实际上只有1*10个,另外的多出的为119,118....n
如果n>119,那么n/100*10 + 10 = 20,110,111,...,119被计算在内是合理的。
所以当末位数为0时,修正值为0,当末位数为2-9时,修正值为i,当末位数为1时,修正值为修正值是(n % i) +1.
//为什么修正值为那么多还有点不太会
源码:
int countDigitOne(int n){
int num = n;
long i = 1;
int s = 0;
while(num>0){
if(num % 10 == 0) //末尾为0时
s += (num / 10) * i ; //修正值为0
if(num % 10 == 1) //末尾为1时
s += (num / 10) * i + (n % i) + 1; //修正值为(n % i)
if(num % 10 > 1) //末为是1~9时
s += (num / 10)* i + i;
num = num / 10;//往后移动一位
i = i*10;
}
return s;
}