1. 程式人生 > >題3:統計數字

題3:統計數字

題目描述:

計算數字k在0到n中的出現的次數,k可能是0~9的一個值
例如n=12,在 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]中,我們發現1出現了5次 (1, 10, 11, 12)
思路一:我們可以用最簡單的辦法先嚐試一下,遍歷1到n中間的每個整數,對每個整數從低位到高位依次檢查,如果有k出現則計數器自加。
思路一最大的問題就是效率,當n非常大時,就需要很長的執行時間。想要提高效率,就要避開暴力法,從數字中找出規律。
思路二:來自《程式設計之美》
假設有一個5位數N=ABCDE,我們現在來考慮百位上出現2的次數,即:從0到ABCDE的數中,有多少個數的百位上是2。分析完它,就可以用同樣的方法去計算個位,十位,千位,萬位等各個位上出現2的次數。
第一種情況:當百位上的數C小於2時:


1)當百位c為0時,比如說12013,0到12013中哪些數的百位會出現2?我們從小的數起, 200~299, 1200~1299, 2200~2299, … , 11200~11299, 也就是固定低3位為200~299,然後高位依次從0到11,共12個。再往下12200~12299 已經大於12013,因此不再往下。所以,當百位為0時,百位出現2的次數只由更高位決定,等於更高位數字(12)x當前位數(100)=1200個。
2)當百位C為1時,比如說12113。分析同上,並且和上面的情況一模一樣。最大也只能到11200~11299,所以百位出現2的次數也是1200個。
上面兩步綜合起來,可以得到以下結論:
—>當某一位的數字小於2時,那麼該位出現2的次數為:更高位數字x當前位數
第二種情況:當百位上的數C等於2時:

當百位C為2時,比如說12213。那麼,我們還是有200~299, 1200~1299, 2200~2299, … , 11200~11299這1200個數,他們的百位為2。但同時,還有一部分12200~12213,共14個(低位數字+1)。所以,當百位數字為2時,百位出現2的次數既受高位影響也受低位影響,結論如下:
—>當某一位的數字等於2時,那麼該位出現2的次數為:更高位數字x當前位數+低位數字+1
第三種情況:當百位上的數C大於2時:
當百位C大於2時,比如說12313,那麼固定低3位為200~299,高位依次可以從0到12,這一次就把12200~12299也包含了,同時也沒低位什麼事情。因此出現2的次數是: (更高位數字+1)x當前位數。結論如下:
—>當某一位的數字大於2時,那麼該位出現2的次數為:(更高位數字+1)x當前位數
通過上述分析,我們可以得到以下規律:
 當某一位的數字小於i時,那麼該位出現i的次數為:更高位數字x當前位數
 當某一位的數字等於i時,那麼該位出現i的次數為:更高位數字x當前位數+低位數字+1
 當某一位的數字大於i時,那麼該位出現i的次數為:(更高位數字+1)x當前位數

程式碼:

#include<iostream>
using namespace std;

class Solution
{
public:
    int digitalCounts1(int n, int k)
    {
        int count = 0;
        for(int i = 1; i <= n; i++)
        {
            intcurNum = i; //當前數字
            while(curNum> 0) //當前數字每一位與1比較
            {
                int temp = curNum % 10; //取當前數字的個位數
                if(temp == k)
                    count++;
                curNum = curNum/10;
            }
        }
        return count;
    }
};

class Solution2
{
public:
    int digitCounts2(int n, int k) 
    {
        int result = 0;
        int base = 1;
        while (n/base > 0) 
        {
            int cur = (n/base)%10;
            int low = n - (n/base) * base;
            int high = n/(base * 10);

            if (cur == k) 
            {
                result += high * base + low + 1;
            } elseif (cur <k) 
            {
                result += high * base;
            } else
            {
                result += (high + 1) * base;
            }
            base *= 10;
        }
        return result;
    }
};
int main()
{
    Solution st1;
    cout<<"--------- 呼叫方法1 -----------"<<endl;
    cout<<"1到12中1出現的次數(12, 1)="<< st1.digitalCounts1(12, 1) <<endl;
    cout<<"1到20中2出現的次數(20, 2)="<< st1.digitalCounts1(20, 2) <<endl;
    cout<<"1到100中9出現的次數(100, 9)="<< st1.digitalCounts1(100, 9) <<endl;
    cout<<endl;
    cout<<"--------- 呼叫方法2 -----------"<<endl;
    Solution2 st2;
    cout<<"1到100中9出現的次數(100, 9)="<< st2.digitCounts2(100, 9) <<endl;
    cout<<"1到12313中3出現的次數(12313, 3)="<< st2.digitCounts2(12313, 3) <<endl;

    system("pause");
    return 0;
}