题目概述
解题思路
我们通过分析样例,来推敲一下这道题的算法流程。假设输入的数n=51302。
我们依次统计输入的数的各个数位可能出现1的数目,需要记录的值还有各个数位的阶数,以及n对它们取模或者除以它们以后的值mod和val。
val | mod | multi | num |
5130 | 2 | 1 | 5130*1 + 1 |
513 | 2 | 10 | 513*10 + 0 |
51 | 302 | 100 | 51*100 + 100 |
5 | 1302 | 1000 | 5*1000 + 303 |
0 | 51302 | 10000 | 0*10000 + 10000 |
由此,我们可以看出一些规律:
- 我们对n共需遍历的次数等于n的位数;
- 各个数位的出现1的次数由两部分构成:
- 第一部分:
- 第二部分:令
,则加
- 第一部分:
方法性能
示例代码
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n)
{
int res = 0, temp_val, temp_mod, multi = 10;
do
{
temp_val = floor(n / multi);
temp_mod = n % multi;
res += temp_val * multi / 10;
if(temp_mod * 10 >= multi)
res += min(multi / 10, temp_mod - multi / 10 + 1);
multi *= 10;
} while (n * 10 >= multi);
return res;
}
};