1. 程式人生 > >程式設計之美--數字1的個數

程式設計之美--數字1的個數

      轉載出處:http://www.cnblogs.com/jy02414216/archive/2011/03/09/1977724.html

1位數的情況:

       在解法二中已經分析過,大於等於1的時候,有1個,小於1就沒有。

       2位數的情況:

       N=13,個位數出現的1的次數為2,分別為1和11,十位數出現1的次數為4,分別為10,11,12,13,所以f(N) = 2+4。

       N=23,個位數出現的1的次數為3,分別為1,11,21,十位數出現1的次數為10,分別為10~19,f(N)=3+10。

       由此我們發現,個位數出現1的次數不僅和個位數有關,和十位數也有關,如果個位數大於等於1,則個位數出現1的次數為十位數的數字加1;如果個位數為0,個位數出現1的次數等於十位數數字。而十位數上出現1的次數也不僅和十位數相關,也和個位數相關:如果十位數字等於1,則十位數上出現1的次數為個位數的數字加1,假如十位數大於1,則十位數上出現1的次數為10。

       3位數的情況:

       N=123

       個位出現1的個數為13:1,11,21,…,91,101,111,121

       十位出現1的個數為20:10~19,110~119

       百位出現1的個數為24:100~123

       我們可以繼續分析4位數,5位數,推匯出下面一般情況:

       假設N,我們要計算百位上出現1的次數,將由三部分決定:百位上的數字,百位以上的數字,百位一下的數字。

       如果百位上的數字為0,則百位上出現1的次數僅由更高位決定,比如12013,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,共1200個。等於更高位數字乘以當前位數,即12 * 100。

       如果百位上的數字大於1,則百位上出現1的次數僅由更高位決定,比如12213,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,12100~12199共1300個。等於更高位數字加1乘以當前位數,即(12 + 1)*100。

如果百位上的數字為1,則百位上出現1的次數不僅受更高位影響,還受低位影響。例如12113,受高位影響出現1的情況:100~199,1100~1199,2100~2199,…,11100~11199,共1200個,但它還受低位影響,出現1的情況是12100~12113,共114個,等於低位數字113+1。

       綜合以上分析,寫出如下程式碼:

複製程式碼 1
public long CountOne2(long n) 2 { 3 long count = 0; 4 long i = 1; 5 long current = 0,after = 0,before = 0; 6 while((n / i) != 0) 7 { 8 current = (n / i) % 10; 9 before = n / (i * 10); 10 after = n - (n / i) * i; 11 12 if (current > 1) 13 count = count + (before + 1) * i; 14 else if (current == 0) 15 count = count + before * i; 16 else if(current == 1) 17 count = count + before * i + after + 1; 18 19 i = i * 10; 20 } 21 return count; 22 23 } 複製程式碼

     此演算法的時間複雜度僅為O(lgN),且沒有遞迴儲存現場的消耗和堆疊溢位的問題。