統計1到N之間所有數字中1的個數
阿新 • • 發佈:2019-01-22
本文中的code和思想來自於https://leetcode.com/discuss/44281/4-lines-o-log-n-c-java-python ,感謝作者
code如下:
int countDigitOne(int n) {
int ones = 0;
for (long long m = 1; m <= n; m *= 10) {
int a = n/m, b = n%m;
ones += (a + 8) / 10 * m + (a % 10 == 1) * (b + 1);
}
return ones;
}
m為從1開始到N之間的所有的10的倍數值。比如1 , 10 ,100 ...
通過m可以將n劃分成為兩個部分,比如數字3141592 , 那麼當m = 100的時候,劃分的結果是31415 和 92 ,那麼百位的字首就是從“ ”到“3141” ,這個看成是3142條的資料,因為這個是百位的字首。那麼百位是1的元素就有,(a/10 + 1)*100個
然後來看看千位,同時千位就是m = 1000 的時候,這個時候可以將數字劃分為 a = 3141 和 b = 592 ,千位的字首就是 從“ ” 到“314” ,一共有315次,然而, 因為千位是1,最後一條只有593 條的資料,也就是 從”000“到”592“ ,所以要分開算。那麼加起來,這個情況一共有( a/10 *1000 ) + (b +1 ) 次
然後比較魔幻的是,上面兩種情況
當a/10 最後一為是 0 ,或者是1 的話,那麼最後一位加上 8 後除以10,那麼還是0 ,但是如果是大於等於2,那麼 就是1了
如果最後一位是1的時候,需要加上b+1 , 如果不是1的話,就不需要,所以上面的公式可以整理成為
((a + 8 )/10 )* m + (a %10 == 1) * (b +1 )