Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.
Example:
Input: 13 Output: 6 Explanation: Digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
/*
从LeetCode看到的答案,很容易理解
原链接 https://leetcode.com/problems/number-of-digit-one/discuss/277541/1
对于数字 abcde (a,b,c,d,e 分别为数字的 万,千,百,十,个 位) 如 23456
从1到abcde,数字1的位 出现的次数为: 个位出现1的次数 + 十位出现1的次数 + 百位出现1的次数 + 千位出现1的次数 万位出现1的次数
以百分位为例求解(个,十,千,万位 也都是一样的)
将abcde 看作 ab c de (a为万分位,b为千分位,c为百分位,d为十分位,e为个分位)。 左半边为ab ,右半边为cd
1到abcde这些数可以分为两个部分: 从1到ab000(不包括ab000) ab000到abcde
从1到ab000(不包括abc00)中, 百分位为1,即c=1出现的次数为:
(00) 1 [00、01、02……99]
(01) 1 [00、01、02……99],
(02) 1 [00、01、02……99]
……
(ab-1) 1 [00、01、02……99]
共ab*100次
在ab000到abcde中,百分位为1,即c=1出现的次数为:
if c>1,那么有 (ab)1[00,01,..99] 共100次
if c==1,那么有 (ab)1[00,01,..de] 共de+1次
if c==0,那么没有,为0次
即,从1到abcde中的数,百分位为1的个数为
ab*100 + 0 if c==0
ab*100 + (de+1) if c==1
ab*100 + 100 if c>0
因此,类推,我们可知:
对于任意分位, 从1到n, 该分位为1的个数为
左半边 * 该分位对应base + 0
左半边 * 该分位对应base + (右半边+1)
左半边 * 该分位对应base + 该分位对应base
左半边指的是 该分位左边组成的数(如上文的例子abcde,百分位,左半边为ab)
右半边指的是 该分位右边组成的数(如上文的例子abcde,百分位,右半边为de)
个分位对应base为1, 十分位对应base为10 , 百分位对应base为 100 , 千分位对应base为 1000
*/
public int NumberOf1Between1AndN_Solution(int n) {
int count=0;
int base=1;//分位对应base(个分位对应1)
int rightPart=0;//该分位右半部分(个分位右边为0)
while(n>0){
int leftPart = n/10;//左半部分
count += leftPart*base;//左半部分*base
int curr = n%10;// n的当前分位
if(curr>1)
count += base;
else if(curr==1){
count += rightPart+1;
}
n /= 10;
rightPart += curr*base;//更新rightPart
base *= 10;//更新base
}
return count;
}