【剑指offer】【数学】43. 1~n整数中1出现的次数

题目链接:https://leetcode-cn.com/problems/1nzheng-shu-zhong-1chu-xian-de-ci-shu-lcof/

按位统计

以abcdef为例,固定其中一位为1,然后统计:

0 ~ ab - 1:
左边:ab:00 ~ ab - 1, ab个
右边:def: 000 ~ 999, 1000个
总数: ab * 1000
ab:
c = 0: 0
c = 1: 0 ~ def; def + 1个
c > 1: 000 ~ 999;1000个

时间复杂度:O(log(n^2)) 以10为底
空间复杂度:O(logn)

class Solution {
public:
    int countDigitOne(int n) {
        if(!n) return 0;
        vector<int> number;
        while(n) number.push_back(n % 10), n /= 10;
        long long res = 0;
        for(int i = number.size() - 1; i >= 0; i--)
        {
            int left = 0, right = 0, t = 1;

            for(int j = number.size() - 1; j > i; j-- )
                left = left * 10 + number[j];

            for(int j = i - 1; j >= 0; j --)
                right = right * 10 + number[j], t *= 10;

            res += left * t;
            if(number[i] == 1) res += right + 1;
            else if(number[i] > 1) res += t;
        }
        return res;
    }
};

优化

思路与上面一样,不过不用 vector来存储数字了,直接计算;
时间复杂度:O(log(n)) 以10为底
空间复杂度:O(1)

class Solution {
public:
    int countDigitOne(int n) {
        if(!n) return n;

        int res = 0, t = 1, m = n;
        while(m > 0)
        {
            t *= 10;
            // 当前位左边的数
            int left = n / t; 
            //当前位的数
            int cur = (n % t) / (t / 10); 
            //当前位右边的数
            int right = (n % t) % (t / 10); 
            m /= 10;

            res += left * t / 10;
            if(cur == 1) res += right + 1;
            if(cur > 1) res += t / 10;
        }

        return res;
    }
};

posted @ 2020-05-03 19:28  NaughtyCoder  阅读(101)  评论(0)    收藏  举报