【Java】 劍指offer(43) 從1到n整數中1出現的次數

本文參考自《劍指offer》一書,代碼採用Java語言。html

更多:《劍指Offer》Java實現合集  java

題目 

 輸入一個整數n,求從1到n這n個整數的十進制表示中1出現的次數。例如輸入12,從1到12這些整數中包含1 的數字有1,10,11和12,1一共出現了5次。post

思路

  若是是從頭至尾遍歷(n次),對每個數字都計算其1的個數(lgn次),則時間複雜度爲O(nlogn),運算效率過低。所以必須總結規律,提升效率。性能

  總結規律以下(思路比《劍指OFFER》一書簡單):測試

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

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

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

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

  3)當前位的數字大於1時,例如n=21034,在十位上的數字cur=3,十位上是1的狀況有:00010~00019,……,21010~21019。一共有(210+1)*10種狀況,即(high+1)*10。it

  這個方法只須要遍歷每一個位數,對於整數n,其位數一共有lgn個,因此時間複雜度爲O(logn)

 

測試算例 

  1.功能測試(3,45,180等)

  2.邊界值測試(0,1等)

  3.性能測試(輸入較大的數字,如1000000等)

Java代碼

//題目:輸入一個整數n,求從1到n這n個整數的十進制表示中1出現的次數。例如
//輸入12,從1到12這些整數中包含1 的數字有1,10,11和12,1一共出現了5次。

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;
    }
}

  

收穫

  1.找規律要耐心!欲速則不達。

  2.學會提取不一樣位置的數字,以及更高、更低位置的數字;學會遍歷每一個位數的循環。

 

更多:《劍指Offer》Java實現合集 

相關文章
相關標籤/搜索