【編程之美】給定一個十進位正整數N,求出從1開始,到N的所有整數,數字1出現的次數。
例如,N=2,則兩個數為1,2 。數字1出現的個數是1.
又如n = 20.則20個數中1出現的為:1,10,11,12,13,14,。。。19 共有12個。
設計一個演算法,可以高效地求出1-N之間出現的1的個數。(主要考慮效率)。
記錄:
對於一個數abcde。出現1的次數可以通過計算各位中出現的1的個數的和計算出來。以統計10位上1的個數為例,記icurrnum為當前要統計的位(例如10位上)的值(d),ilow為icurrnum低位的值(e),ihighnum為icurrnum高位的值(abc).
則根據icurr的值,出現1的個數可以歸納為:
i . icurrnum == 0; 則10位上出現1的次數由更高位的abc決定,且次數等於ihighnum * 10;
ii .icurrnum == 1;則10位上出現1的次數由高位和低位共同決定,次數等於 ihighnum*10 + ilownum+1
iii icurrnum >1, 則10位上1的次數由高位決定,且次數等於(ihigh+1) *10;
一次計算個位,10位,百位。。。等出現1的個數,相加,就是最終的結果。
編碼【改自編程之美P135】
#include <stdio.h>int sum(int n){ int icount = 0; int ifactor = 1; int ilowernum = 0; int icurrnum = 0; int ihighnum = 0; while(n/ifactor != 0){ ilowernum = n-(n/ifactor)*ifactor; icurrnum = (n/ifactor)%10; ihighnum = n/(ifactor*10); switch(icurrnum){ case 0:icount +=ihighnum*ifactor;break; case 1:icount +=ihighnum*ifactor+ilowernum+1;break; default:icount +=(ihighnum + 1) * ifactor;break; } ifactor *=10; } return icount;}main(){ int n; while(true){ scanf("%d",&n); printf("the count of 1 is :%d\n",sum(n)); } return 0;}
如果數字過大,用long long 類型替代int.