求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有一、十、十一、十二、13所以共出現6次,可是對於後面問題他就沒轍了。ACMer但願大家幫幫他,並把問題更加廣泛化,能夠很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。函數
能夠編寫一個判斷一個數字有多少個1的函數,而後遍歷1-n依次調用統計函數,最後求和便可,不過這樣時間複雜度有些多。spa
咱們能夠按數字的位數來依次統計1出現的個數,例如21345這個數,咱們先看1346-21345區間1出現的個數。code
先統計萬位出現1的個數,咱們知道,10000-19999,萬位共出現了10000次,也就是10^4個1,考慮一下特殊狀況,若是是12345這樣的數,實際上萬位出現1的個數就等於萬位後面的數字加1,也就是2345+1=2346次。blog
再來計算後面,也就是其他4位1出現的次數1346-21345能夠拆成兩部分來看,一部分是1346-11345,每一段剩下的4位數字中,選擇1位是1,其他三位能夠選擇0-9,也就是出現了10^3次,共4位因此也就是4*10^3次,同理剩下的部分11346-21345也是4*10^3次。遞歸
而剩下的1-1345區間出現1的個數能夠經過遞歸求得。io
C++class
class Solution { public: int NumberOf1Between1AndN_Solution(int n) { int length = 0; int num = n; while(num){ num /= 10; length++; } return helper(n, length); } int helper(int num, int length){ if(length == 0 || num <= 0) return 0; int numfirst = 0; int first = num / pow(length-1); if(length == 1 && first > 0) return 1; if(first > 1){ numfirst = pow(length-1); } if(first == 1){ numfirst = num - pow(length-1) + 1; } int numother = first * (length - 1) * pow(length-2); return numfirst + numother + helper(num - first*pow(length-1), length-1); } int pow(int num){ int res = 1; for(int i = 0; i < num; ++i) res *= 10; return res; } };
Java遍歷
public class Solution { public int NumberOf1Between1AndN_Solution(int n) { if(n <= 0) return 0; int res = 0; while(n != 0){ res += helper(n); n--; } return res; } public int helper(int n){ int count = 0; while(n != 0){ if(n % 10 == 1) count++; n /= 10; } return count; } }