29-1 :從1 到n的整數中1出現的次數

一、題目
輸入一個整數n,求從1 到n這n個整數的十進制表示中1 出現的次數。
舉例說明:
例如輸入12 ,從1 到12 這些整數中包含1 的數字有1、10、11 和12,1 一共出現了5 次。
二、解題思路
第一種:不考慮時間效率的解法
累加1 到n 中每個整數中1出現的次數。我們可以每次通過對10 求餘數判斷整數的個位數字是不是1 。如果這個數字大於10,除以10 之後再判斷個位數字是不是1
  如果是從頭到尾遍歷(n次),對每一個數字都計算其1的個數(lgn次),則時間複雜度爲O(nlogn),運算效率太低。因此必須總結規律,提高效率。

 public static int numberOf1Between1AndN(int n) {
        if (n < 0) {
            return 0;
        }
        int count = 0;

        for (int i = 1; i <= n; i++) {
            count += numberOf1(i);
        }
        return count;
    }

    public static int numberOf1(int n) {
        int count = 0;
        while (n > 0) {
            count += (n % 10 == 1) ? 1 : 0;
            n = n / 10;
        }

        return count;
    }

第二種:從數字規律着手明顯提高時間效率的解法

規律:

1:如果第i位(從低位向高位開始)上的數字是0,那麼第i位可能出現1的次數僅由更高位決定(如果沒有高位,則視高位爲0),等於更高位數字*當前位數的權重10^(i-1);

2:如果第i位上的數字爲1,則第i位上可能出現1的次數不僅受更高位影響還受低位影響(如果沒有低位,則視低位爲0),等於更高位數字*當前位數的權重10^(i-1) + (低位數字+1);

3:如果第i位上的數字大於1,則第i位上可能出現1的次數僅由更高位決定(如果沒有高位,則視高位爲0),等於(更高位數字+1)*當前位數的權重10^(i-1)。

原文鏈接:https://blog.csdn.net/u013132035/article/details/80768636


以21354爲例,尋找1出現的次數:

個位:從1至21350中包含了2135個10,因此1出現了2135次,21351,21352,21353,21354其中21351包含了一個1,故個位出現1的次數爲:2135*10(1-1) + 1 = 2136次;

公式:( 2135+1)* 10^(1-1) = 2136;

十位:從1到21300中包含了213個100,因此1出現了213 * 10^(2-1) = 2130次,剩下的數字是21301到21354,它們的十位數字是5 > 1;因此它會包含10個1;故總數爲2130 + 10 = 2140次;

公式:(213 + 1)* 10^(2-1) = 2140次;

百位:從1到21000中包含了21個1000,因此1出現了21 * 10^(3-1) = 2100次,剩下的數字是21001到21354,它們的百位數字是3 > 1;因此它會包含100個1;故總數爲2100 + 100 = 2200次;

公式:(21 + 1)* 10^(3-1) = 2200次;

千位:從1到20000中包含了2個10000,因此1出現了2 * 10^(4-1) = 2000次,剩下的數字是20001到21354,它們的千位數字是1 = 1;情況稍微複雜些,354 + 1 = 355;故1的總數爲2000 + 355 = 2355次;

公式:2 * 10^(4-1) + 354 + 1 = 2355次;

萬位:萬位是2 > 1,沒有更高位;因此1出現的次數是1 * 10^(5-1) = 10000次;

公式:(0 + 1)*10^(5-1) = 10000次;

故總共爲:2136+2140+2200+2355+10000=18831次;
原文鏈接:https://blog.csdn.net/u013132035/article/details/80768636


對於整數n,我們將這個整數分爲三部分:當前位數字cur,更高位數字high,更低位數字low,如:對於n=21034,當位數是十位時,cur=3,high=210,low=4。

我們從個位到最高位 依次計算每個位置出現1的次數:

1)當前位的數字等於0時,例如n=21034,在百位上的數字cur=0,百位上是1的情況有:00100-00199,01100-01199,……,20100~20199。一共有21*100種情況,即high *100;

2)當前位的數字等於1時,例如n=21034,在千位上的數字cur=1,千位上是1的情況有:01000-01999,11000-11999,21000~21034。一共有2*1000+(34+1)種情況,即 high *1000+(low+1)。

3)當前位的數字大於1時,例如n=21034,在十位上的數字cur=3,十位上是1的情況有:00010-00019,……,21010~21019。一共有(210+1)*10種情況,即(high+1)*10。
這個方法只需要遍歷每個位數,對於整數n,其位數一共有lgn個,所以時間複雜度爲O(logn)。
原文鏈接:https://www.cnblogs.com/yongh/p/9947165.html

public class NumberOf1 {
    public int NumberOf1Between1AndN_Solution(int n) {
        int count=0;
        for(int i=1;i<=n;i*=10){  //i代表位數
            int high=n/(i*10); //更高位數字
            int low=(n%i);  //更低位數字
            int cur=(n/i)%10;  //當前位數字
            if(cur==0){
                count+=high*i;
            }else if(cur==1){
                count+=high*i+(low+1);
            }else{
                count+=(high+1)*i;
            }
        }
        return count;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章