解法一:计算高低位(推荐,因为十分利于理解)

思路

若百位上数字为 0,百位上可能出现 1 的次数由更高位决定;若百位上数字为 1,百位上可能出现 1 的次数不仅受更高位影响还受低位影响;若百位上数字大于 1,则百位上出现 1 的情况仅由更高位决定。

代码

图片说明

解法二:公式法(其实和解法一一致)

思路

只要理解了解法一,解法二就能够完全理解,直接看代码即可,加8就是因为,只要当前位比1大那就肯定覆盖了所有1的部分,就像212和220虽然相差了8但是他们含有的1的个数是完全一样多的

代码

public class Solution {
    public int NumberOf1Between1AndN_Solution(int n) {
        if (n <= 0)
            return 0;
        int count = 0;
        for (int m = 1; m <= n; m *= 10) {
            int a = n / m, b = n % m;//a为当前位,b为当前位的余数(个位的余数就是本身)
            count += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1 : 0);
        }
        return count;
    }
}