Given an integer n, count the total number of digit 1 appearing in all non-negative integers less than or equal to n. For example: Given n = 13, Return 6, because digit 1 occurred in the following numbers: 1, 10, 11, 12, 13.
計算全部小於等於n的正整數中數字1的個數。
好比比13小的正整數中包含1的有1,10,11,12,13
,一共有6個1。git
若是使用暴力循環的話,那麼咱們只須要遍歷全部小於n的正整數,計算該正整數中包含幾個1並將返回這些結果的和。可是,這種方法浪費了不少沒必要要的計算。好比在小於n的正整數中,有不少甚至都一個1都沒有。所以,咱們須要用更好的方法,減小這種方法的浪費。面試
咱們隨意找一個數來入手,假設如今n爲52
,那麼52
下含有的1實際上等於50~52 + 1~49
中有的1,也就等價於0~2 + 1~49
中含有的1。
在這裏咱們很清楚的知道,當n<10時,只有1個1。所以0~2
只有1個1。微信
咱們再來拆解1~49
。1~49
其實等價於40~49 + 30~39 + 20~29 + 10~19 + 1~9
中的1的個數。咱們再分析一下就會發現,40~49
, 30~39
, 20~29
, 0~9
中的1的個數是相同的!而特殊的狀況是10~19
,它的1的數量其實等於10 + 0~9
。app
總結一下咱們知道countDigitOne(52) = countDigitOne(2) + countDigitOne(9) * 5 + 10
。less
這裏其實還有一個特殊狀況,就是當最高位剛好爲1的時候,舉個例子135
。那麼100~135
等價於36+0~35
個1,那麼countDigitOne(135) = 36 + countDigitOne(35) + countDigitOne(99)
。spa
整理爲代碼以下:code
public int countDigitOne(int n) { if(n <= 0) return 0; if(n < 10) return 1; int count = 1; while(n / count > 9){ count *= 10; } if(n / count == 1){ return n % count + 1 + countDigitOne(n%count) + countDigitOne(count-1); }else{ return countDigitOne(n % count) + count + (n/count) * countDigitOne(count-1); } }
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~教程