题目:
求出1~n之间的整数中1出现的次数。其中n为任意非负整数。
解法:
注意是出现的次数:例如数字11,1出现的次数为2次。
1、本题的思想是从最低位开始求1出现的次数。
2、然后把所有位1出现的次数相加。
eg:n=12345,( n=abcde ) 例如要求百位为1的数字的个数。
一共分两步走。先求0~12299 中百位 为1的数字。再求12300~12345中百位为1的数字。
(一)0~12299 中百位为1的形式如下: ab 1 cd ,ab可取得组合为0~(ab-1)一共ab种,
对于本例即 在百位的前半部分 可取(00,01,02,03……11),即一共有ab=n/(exp*10)种取法,后半段可取的范围是(0,1,2,……99)一共exp种,其中exp代表当前位,此时求的是百位,因此exp=100. 所以在第一部分中 百位出现1的情况
即为 n/(exp*10) * (exp).
(二)对于12300~12345中的部分。先确定百位上的数字是否为1,此时高位只能取ab.对于此案例只能取12.
若百位为1. 则出现的数字为 00~ef 共(ef+1)种。
若百位大于1.则一共可取00~99 共exp种。
若百位为0,没有数字满足条件。
代码如下:
int NumberOf1Between1AndN_Solution(int n)
{
if(n<=0)
return 0;
int exp = 1;
int ans = 0;
while(n/exp)// 求每一位上出现1 的数字的个数。 再把所有位出现1的个数相加,即可1出现的次数
{
ans = ans + n/(exp*10)*exp;//n/(exp*10)为对应位左边的取值情况,exp为对应位右边的取值情况(0~exp-1)共exp中取法
if(n%(exp*10)/exp >1)//对应位> 1 的情况下,小于对应位的数为0~exp
ans = ans + exp;
else if(n%(exp*10)/exp ==1)//对应位== 1的情况下,小于对应位的数为0~ n%exp
ans = ans +n%exp+1;
exp =exp*10;
}
return ans;
}