整數中1出現的次數(從1到n整數中1出現的次數)劍指offer 面試題43

題目描述:

求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,可以很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。

解題思路:

例如求解:1-21345之間的出現的1的個數;分段處理:1-1345;1346-21345。

1346-21345的最高位的1的個數:10000-19999 1的數量10^4個,如果最高位不是2,是1(數字爲11345);則爲1345+1。

剩下的四位當中1的個數:1346-11345  1的數量4*10^3,11346-21345 1的數量4*10^3。 規律最高位數值*位數減1*10^(位數減2)

1-1345 則遞歸調用函數即可求得

通過的C++代碼:

#include <cstdlib>
class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        if(n <= 0)
            return 0;
        char strNum[50];
        sprintf(strNum,"%d",n);
        return numberOf1(strNum);
    }
    int numberOf1(const char * strNum)
    {
        if(!strNum || *strNum < '0' || *strNum > '9' || *strNum == '\0')
            return 0;
        int first = *strNum - '0';
        //strlen獲取的是char*字符串的真實長度,不包括'\0';而sizeof()是變量聲明後佔用的字節數,不是實際長度
        unsigned int len = static_cast<unsigned int>(strlen(strNum));
        if(len == 1 && first == 0)
            return 0;
        if(len == 1 && first > 0)
            return 1;
        //假設數字是21345
        //numFirstDigit 是第一位爲1的數目
        int numFirstDigit = 0;
        if(first == 1)
        {
            numFirstDigit = atoi(strNum+1)+1;
        }
        else if(first > 1)
            numFirstDigit = powerBase10(len - 1);
        //numOtherDigits 表示1346-21345除了第一位之外的1的位數
        int numOtherDigits = 0;
        numOtherDigits = first * (len-1) * powerBase10(len - 2);
        //numRecursive 表示1-1345的1的位數,遞歸的求解
        int numRecursive = 0;
        numRecursive = numberOf1(strNum + 1);
        return numFirstDigit + numOtherDigits + numRecursive;
    }
    int powerBase10(unsigned int len)
    {
        int result = 1;
        for(int i=0; i<len; ++i)
            result *= 10;
        return result;
    }
};

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章