Lintcode: Digit Counts


Count the number of k's between 0 and n. k can be 0 - 9.

Example
if n=12, in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], we have FIVE 1's (1, 10, 11, 12)

方法一: Brute Force, 0到n個數挨個算過去。最大的問題就是效率,當n非常大時,就需要很長的運行時間。

方法二:參考http://www.hawstein.com/posts/20.4.html分析一下會發現有如下結論

當某一位的數字小於i時,那么該位出現i的次數為:更高位數字x當前位數
當某一位的數字等於i時,那么該位出現i的次數為:更高位數字x當前位數+低位數字+1
當某一位的數字大於i時,那么該位出現i的次數為:(更高位數字+1)x當前位數

假設一個5位數N=abcde,我們現在來考慮百位上出現2的次數,即,從0到abcde的數中, 有多少個數的百位上是2。分析完它,就可以用同樣的方法去計算個位,十位,千位, 萬位等各個位上出現2的次數。

當百位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個。

當百位c為1時,比如說12113。分析同上,並且和上面的情況一模一樣。 最大也只能到11200~11299,所以百位出現2的次數也是1200個。

上面兩步綜合起來,可以得到以下結論:

當某一位的數字小於2時,那么該位出現2的次數為:更高位數字x當前位數

當百位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時,比如說12313,那么固定低3位為200~299,高位依次可以從0到12, 這一次就把12200~12299也包含了,同時也沒低位什么事情。因此出現2的次數是: (更高位數字+1)x當前位數。結論如下:

當某一位的數字大於2時,那么該位出現2的次數為:(更高位數字+1)x當前位數

 1 class Solution {
 2     /*
 3      * param k : As description.
 4      * param n : As description.
 5      * return: An integer denote the count of digit k in 1..n
 6      */
 7     public int digitCounts(int k, int n) {
 8         int count = 0;
 9         int base = 1;
10         while (n / base >= 1) {
11             int curBit = n % (base*10) / base;
12             int higher = n / (base*10);
13             int lower = n % base;
14             if (curBit < k) {
15                 count += higher * base;
16             }
17             else if (curBit == k) {
18                 count += higher * base + lower + 1;
19             }
20             else {
21                 count += (higher + 1) * base;
22             }
23             base *= 10;
24         }
25         return count;
26     }
27 };

別人的同樣做法的code:

 1     public int digitCounts(int k, int n) {
 2         // write your code here
 3         int result = 0;
 4         int base = 1;
 5         while (n/base > 0) {
 6             int cur = (n/base)%10;
 7             int low = n - (n/base) * base;
 8             int high = n/(base * 10);
 9 
10             if (cur == k) {
11                 result += high * base + low + 1;
12             } else if (cur < k) {
13                 result += high * base;
14             } else {
15                 result += (high + 1) * base;
16             }
17             base *= 10;
18         }
19         return result;
20     }

Brute Force:

 1 class Solution {
 2     /*
 3      * param k : As description.
 4      * param n : As description.
 5      * return: An integer denote the count of digit k in 1..n
 6      */
 7     public int digitCounts(int k, int n) {
 8         int sum = 0;
 9         char kk = (char)('0' + k);
10         for (int i=0; i<=n; i++) {
11             String ii = Integer.toString(i);
12             for (int j=0; j<ii.length(); j++) {
13                 if (ii.charAt(j) == kk) sum++;
14             }
15         }
16         return sum;
17     }
18 };

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM