题目描述:
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
分析:
找规律。
该数字(不包括该数)以内 | 出现1的次数 |
1 | 0 |
10 | 1 |
100 | 20 |
1000 | 300 |
2 | 0+1+0=1 |
20 | 1+10+1=12 |
200 | 20+100+20=140 |
2000 | 300+1000+300=1600 |
3 | 1+0=1 |
30 | 12+1=13 |
300 | 140+20=160 |
m*10^i这个数(不含这个数):
如果m=1,那么这个数以内有(m*i*10^(i-1))个1。
如果m>1,那么这个数以内有(m*i*10^(i-1)+10^i)个1。
那么如果给出一个数,我们可以拆分每一位。
例如给出的数是1213的话,那么我们可以求
1000以内1的个数+200以内1的个数+10以内1的个数+3以内1的个数,
另外我们还需要加上213再加上3,因为它们的前一个位数字都是1;而且我们还要再加上2,因为本身1213中有2个1,我们之前算的一直都是不含本身的。
更加直观的讲就是,1213,求0~999中1的个数+1000~1199中1的个数+1200~1209中1的个数+1210~1212中1的个数+1213中1的个数。
213从1000~1199、1200~1209、1210~1212中的第一个1来的。
3从1210~1212中的第三个1来的。
代码:
1 class Solution { 2 public: 3 int NumberOf1Between1AndN_Solution(int n) { 4 int n1 = n; 5 int i = 0; // 0的个数 6 int ei = 1; // 10^i 7 int ans = 0; 8 while(n1) { 9 int m = n1 % 10; // 首位 10 ans += m * i * ei / 10; 11 if(m > 1) ans += ei; 12 if(m == 1) ans += n % ei + 1; 13 ei *= 10; 14 i++; 15 n1 /= 10; 16 } 17 return ans; 18 } 19 };