1~n整数中1出现的次数
题目
输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。( 1 < = n < 2 3 1 1 <= n < 2^31 1<=n<231)
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次。
思路 找规律 参考leetcode题解:
以5014为例找规律:
- 个位出现1的个数:
记高位为high=501,当前位current=4。
高位在0~500变化时,每个变化只出现1次,即(×××1)这样的数字;
高位=501时,当前位是4,1只出现1次,即5011;
故一共出现的次数是 h i g h ∗ 1 + 1 = 502 high*1+1=502 high∗1+1=502。 - 十位出现1的个数:
记高位为high=50,当前位current=1,低位low=4。
高位在0~49变化时,每个变化1出现10次,即(××10 ~ ××19)这样的数字;
高位=50时,当前位=1,低位=4,所以一共出现5次,即5010~5014;
故一共出现的次数是 h i g h ∗ 10 + 4 + 1 = 505 high*10+4+1=505 high∗10+4+1=505。 - 百位出现1的个数:
记高位为high=5,当前位current=0,低位low=14。
高位在0~4变化时,每个变化1出现100次,即(×100 ~ ×199)这样的数字;
高位=5时,当前位=0,低位=14,百位为0不存在出现1的可能性;
故一共出现的次数是 h i g h ∗ 100 + 0 = 500 high*100+0=500 high∗100+0=500。 - 千位出现1的个数:
记高位为high=0,当前位current=5,低位low=014。
高位不存在变化,直接看当前位;
因为当前位为5,所以1出现的次数为1000,即1000~1999这样的数字;
故一共出现的次数是 h i g h ∗ 1000 + 1000 = 1000 high*1000+1000=1000 high∗1000+1000=1000。 - 最后把各个位上出现1的次数累加得到最终答案2507。
结论:
假设高位为high,当前位为current,低位为low,i代表着需要统计的位置数(1对应个位,10对应十位,100对应百位),则对每一位的个数count有:
- current=0: c o u n t = h i g h ∗ i count = high*i count=high∗i;
- current=1: c o u n t = h i g h ∗ i + l o w + 1 count = high*i+low+1 count=high∗i+low+1;
- current>1: c o u n t = h i g h ∗ i + i count = high*i+i count=high∗i+i;
C++
class Solution {
public:
int countDigitOne(int n) {
int count = 0;
long i = 1; //指向遍历的位数:i=1表示个位、i=10表示十位
while(n/i) //遍历n的所有位
{
long high = n/(10*i); //将当前位之前的所有高位都存在high中
long current = (n/i)%10; //当前位,统计该位上出现1的次数
long low = n-(n/i)*i;
if(current==0)
count += high*i;
else if(current==1)
count += high*i + low + 1;
else
count += high*i + i;
i *= 10; //遍历下一位
}
return count;
}
};
python
class Solution:
def countDigitOne(self, n: int) -> int:
count = 0
i = 1
while n//i:
high = n//(i*10)
current = (n//i)%10
low = n-(n//i)*i
if current == 0:
count += high*i
elif current == 1:
count += high*i + low + 1
else:
count += high*i + i
i *= 10
return count