当n = 216;
- 个位上为1,216/10 + 1 * 1即01,11,21,..201; 211;
- 十位上为1:设x代表一个(0-9)的数字。先不考虑210-216上十位的1。
在1x-11x个位上可以取0-9即(21/10)*10。
最后考虑21X的情况,因为X不一定能取到0-9。即210-216 共7个 216%10+1。 - 其他位置类似。
当n = 206;
- 个位上为1,206/10 + 1 。
- 十位上为1:设x代表一个(0-9)的数字。先不考虑200-206上十位的1。
在1x-11x个位上可以取0-9即(20/10)*10。
最后考虑20X的情况,因为20%10 ==0,21X取不到,不考虑相加。
当n = 226;
- 个位上为1,226/10 + 1 。
- 十位上为1:设x代表一个(0-9)的数字。先不考虑220-226上十位的1。
在1x-11x个位上可以取0-9即(22/10)*10。
最后考虑22X的情况,因为22%10>1,210-219都可以取到,共10个;
因此当低位为1,0,大于1,判断的条件不同。
- 当为1时和后面数字有关。
- 当为0时和后面数字无关。
- 当大于1时和后面数字无关。
+8是为了来减少当a的低位大于1的情况的判断,仅此而已。
+9是混淆当a的低位为1和>1的不同相加情况。
当a的低位为1时,补8不会进位,a/10==(a+8)/10,但需要a的后面数字的值。
当a的低位>1,补8会产生进位,效果等同于(a/10+1)*m,不需要再加。
当a的低位为0,补8不会进位,效果等同于a/10==(a+8)/10,也不需要再加。
cnt += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1 : 0); 等价 cnt += a / 10 * m + (a % 10 == 1 ? b + 1 : 0)+ (a % 10 > 1 ? m : 0);
class Solution{ public : int NumberOf1Between1AndN_Solution(int n) { int cnt = 0; // 统计1的个数 for (int m = 1; m <= n; m *= 10) { int a = n / m, b = n % m; cnt += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1 : 0); } return cnt; } };