43. 1~n 整数中 1 出现的次数

1. 描述

输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。
例如,输入12,1~12这些整数中包含1 的数字有1、10、11和12,1一共出现了5次

2. 例子

示例 1:
输入:n = 12
输出:5

示例 2:
输入:n = 13
输出:6

3. 限制

  • 1 <= n < $2^{31}$

4. 题解

时间复杂度: O($log_{10}n$)
空间复杂度: O(1)

为了快速解题,肯定是要找规律
为了找到数字 1 出现的规律,我们随便找一个数字来分析一下,以数字 12045 为例,个位数过于特殊,我们来分析十位数
12045 中的十位数是 4,十位数 1 可能出现的地方是其左边 12000 以及其十分位自身 45
左边 12000 中出现的十分位数字非常容易理解,十分位数字可能出现的地方是 10~19,共十个数字,而这一循环每 100 个数字出现一次,所以左边 12000 中出现十分位数字 1 的次数一共是 12000 / 100 * 10
45 出现十分位数字 1 的情况需要讨论,如果出现的数字是 09 呢?根本没有十分位没有什么好说的,如果是 15 呢?那就是 10~15 共 6 个数字,如果是 45 呢?45 又怎么样,19 之后的数字都是一样的,反正最多贡献 10 个十分位数字。所以再来看下我们的分界线,是 10 和 20,10 的由来是因为十分位,如果是百分位,那分界线自然是 100。

class Solution 
{
public:
    int countDigitOne(int n)
    {
        int digitOneCount = 0;
        for(long base = 1; base <= n; base *= 10)
        {
            long divider = base * 10;
            int leftOneDigit = n / divider * base;
            
            int basePositionNumber = n % divider;
            int currentOneDigit = (basePositionNumber < base ? 0 : min(base, basePositionNumber - base + 1));
            
            digitOneCount += leftOneDigit + currentOneDigit;
        }
        
        return digitOneCount;
    }
};
Last updated:
Tags: 数学
comments powered by Disqus