關於劍指offer上“從1到n整數中1出現的次數”題的理解
阿新 • • 發佈:2018-11-01
寫這篇部落格是因為,看完劍指offer上這道題的解釋後,我確實是沒有看懂。所以按照我的思路重新描述一下這道題到底要怎麼做。
題目描述:
輸入一個整數n,求從1到n這n個整數的十進位制表示中1出現的次數
首先想到的肯定是暴力法,這裡就不多說了。
更優化的方法需要我們先列舉幾個數來找找規律。
假設用i表示當前的數位
(1)當i位為0時,比如12034,顯然當前位是第三位,那麼第三位出現1的情況有哪些呢?
100~199
1100~1199
2100~2199
3100~3199
.....
10100~10199
11100~11199
一共是12*100 = 1200個數
也就是0的高位數12乘以當前位數(第三位的位數是100,第二位是10,以此類推)
(2)當第i位為1時,比如12134,那麼第三位出現1的情況有哪些?
100~199
1100~1199
2100~2199
3100~3199
.....
10100~10199
11100~11199
12100~12134即12*100+(34+1) = 1235個數
也就是0的高位數12乘以當前位數100,然後加上低位數+1,得到的值
(3)當第i位大於1時,比如12433,那麼第三位出現1的情況有哪些?
100~199
1100~1199
2100~2199
3100~3199
.....
10100~10199
11100~11199
12100~12199即13*100
也就是0的高位數+1然後乘以當前位數100
按照上述規律,對每一位求出現1的數,最後累加即可得到結果。
程式碼如下:
int NumberOf1Between1AndN_Solution(int n){ int count = 0; //1的個數 int i=1; //當前位 int current = 0, after = 0, before = 0; //比如n=12345,i=100 //current = 3 //before = 12 //after = 45 while((n/i) != 0){ current = (n/i) % 10; //當前位的數字 before = n/(i*10); //當前位及之前的數字 after = n - (n/i)*i; //低位數字 //如果當前位為0,出現1的次數由高位覺得,等於高位數字*當前位數 if(current == 0){ count += before * i; }else if(current == 1){ //如果當前位為1,出現1的次數由高位和低位決定,高位*當前位+低位+1 count += before*i + after + 1; }else{ //如果大於1,出現1的次數由高位決定,(高位數字+1)*當前位數 count += (before+1)*i; } //前移一位 i = i * 10; } return count; }
牛客網上可測試程式碼是否正確
https://www.nowcoder.com/questionTerminal/bd7f978302044eee894445e244c7eee6