本文參考自《劍指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等)
//題目:輸入一個整數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.學會提取不一樣位置的數字,以及更高、更低位置的數字;學會遍歷每一個位數的循環。