【LeetCode】233. Number of Digit One

Number of Digit One

Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n.

For example:
Given n = 13,
Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.

Hint:

    1. Beware of overflow.

难题的惯例是先上保底做法。逐个数字数1,累加。

虽然知道会TLE,总比空着白板好。

class Solution {
public:
    int countDigitOne(int n) {
        int ret = 0;
        if(n <= 0)
            return ret;
        for(int i = 1; i <= n; i ++)
        {
            ret += countOne(i);
        }
        return ret;
    }
    int countOne(int n)
    {
        int ret = 0;
        while(n)
        {
            if(n % 10 == 1)
                ret ++;
            n /= 10;
        }
        return ret;
    }
};

下面上标准做法,参考了编程之美。

这题可以扩展为其他进制的情况。

从右到左逐位计数当前位置(记为cur)为1的所有数字。

(1)cur为0时,需要计数的部分为:cur位置为1,然后对于高位0~high-1的每个值,低位遍历0~divisor。

因此总数为high * divisor

(2)cur为1时,需要计数的部分为:除了上述cur为0的部分,再补充cur为1时,低位遍历0~low。

因此总数为high * divisor + low + 1

(3)cur为其他数时,需要计数的部分为:

cur位置为1,然后对于高位0~high的每个值,低位遍历0~divisor。

因此总数为(high + 1) * divisor

class Solution {
public:
    int countDigitOne(int n) {
        if(n <= 0)
            return 0;
        int ret = 0;
        int base = 10;
        long long divisor = 1;
        while(n / divisor)
        {
            int high = n / (divisor * base);
            int cur = n / divisor % base;
            int low = n - n / divisor * divisor;
            if(cur == 0)
                ret = ret + high * divisor;
            else if(cur == 1)
                ret = ret + high * divisor + low + 1;
            else
                ret = ret + (high + 1) * divisor;
            divisor *= base;
        }
        return ret;
    }
};

原文地址:https://www.cnblogs.com/ganganloveu/p/4642551.html