【Java】 劍指offer(43) 從1到n整數中1出現的次數 《劍指Offer》Java實現合集 《劍指Offer》Java實現合集
本文參考自《劍指offer》一書,程式碼採用Java語言。
題目
輸入一個整數n,求從1到n這n個整數的十進位制表示中1出現的次數。例如輸入12,從1到12這些整數中包含1 的數字有1,10,11和12,1一共出現了5次。
思路
如果是從頭到尾遍歷(n次),對每一個數字都計算其1的個數(lgn次),則時間複雜度為O(nlogn),運算效率太低。因此必須總結規律,提高效率。
總結規律如下(思路比《劍指OFFER》一書簡單):
對於整數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)。
測試算例
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.學會提取不同位置的數字,以及更高、更低位置的數字;學會遍歷每個位數的迴圈。