我可太喜歡這個題了

      網(wǎng)友投稿 877 2025-04-04

      今天我們來看一道賊棒的題目,題目不長,很經(jīng)典,也很容易理解,我們一起來看一哈吧,

      大家也可能做過這道題,那就再復習一下唄,如果沒做過的話,可以看完文章,自己去 AC 一下,不過寫代碼的時候,要自己完全寫出來,這樣才能有收獲,下面我們看題目吧。

      leetcode 233. 數(shù)字 1 的個數(shù)

      題目描述

      給定一個整數(shù) n,計算所有小于等于 n 的非負整數(shù)中數(shù)字 1 出現(xiàn)的個數(shù)。

      示例 1:

      輸入:n = 13 輸出:6

      示例 2:

      輸入:n = 0 輸出:0

      太喜歡這種簡潔的題目啦,言簡意賅,就是讓咱們找出小于等于 n 的非負整數(shù)中數(shù)字 1 出現(xiàn)的個數(shù)。

      大家看到這個題目的第一印象,可能會這樣想,哦,讓我們求 1 的個數(shù)。

      吶我們直接逐位遍歷每個數(shù)的每一位,當遇到 1 的時候,計數(shù)器 +1,不就行了。

      嗯,很棒的方法,可惜會超時。

      或者說,我們可以先將所有數(shù)字拼接起來,然后再逐位遍歷,這樣仍會超時。

      大家再思考一下還有沒有別的方法呢?

      既然題目讓我們統(tǒng)計小于等于 n 的非負整數(shù)中數(shù)字 1 出現(xiàn)的個數(shù)。

      那我們可以不可這樣統(tǒng)計。

      我們假設(shè) n = abcd,某個四位數(shù)。

      那我們完全可以統(tǒng)計每一位上 1 出現(xiàn)的次數(shù),個數(shù)上 1 出現(xiàn)的次數(shù),十位上 1 出現(xiàn)的次數(shù),百位 ,千位......

      也就是說小于等于 n 的所有數(shù)字中,個位上出現(xiàn) 1 的次數(shù) + 十位出現(xiàn) 1 的次數(shù) + ...... 最后得到的就是總的出現(xiàn)次數(shù)。

      見下圖

      我們假設(shè) n = ?13 (用個小點的數(shù),比較容易舉例)

      我可太喜歡這個題了

      我們需要統(tǒng)計小于等于 13 的數(shù)中,出現(xiàn) 1 的次數(shù),

      通過上圖可知,個位上 1 出現(xiàn) 2 次,十位上 1 出現(xiàn) 4 次

      那么總次數(shù)為 2 + 4 = 6 次。

      另外我們發(fā)現(xiàn) 11 這個數(shù),會被統(tǒng)計 2 次,它的十位和個位都為 1

      我們這個題目是要統(tǒng)計 1 出現(xiàn)的次數(shù),而不是統(tǒng)計包含 1 的整數(shù),所以上訴方法不會出現(xiàn)重復統(tǒng)計的情況。

      我們題目已經(jīng)有大概思路啦,下面的難點就是如何統(tǒng)計每一位中 1 出現(xiàn)的次數(shù)呢?

      我們完全可以通過遍歷 n 的每一位來得到總個數(shù),見下圖

      假設(shè)我們想要得到十位上 1 出現(xiàn)的次數(shù),當前我們指針指向十位,

      我們稱之為當前位。num 則代表當前位的位因子,當前位為個位時 num = 1,十位時為 10,百位時為 100....

      那我們將當前位左邊的定義為高位,當前位右邊的定義位低位。

      例:n = 1004 ,此時指針指向十位(當前位)num = 10,高位為百位,千位,低位為個位

      而且我們發(fā)現(xiàn)數(shù)字的某一位的取值范圍為 0 ~ 9 ,那么我們可以將這 10 個數(shù)分為 3 類,小于 1 (當前位數(shù)字為 0 ),等于 1(當前位數(shù)字為 1 ) ,大于 1(當前位上數(shù)字為 2 ~ 9),下面我們就來分別考慮三種情況。

      我們進行舉例的 n 為 1004,1014,1024。重點討論十位上 3 種不同情況。

      大家閱讀下方文字之前,先想象自己腦子里有一個行李箱的滾輪密碼鎖,我們固定其中的某一位,然后可以隨意滑動其他位,這樣可以幫助大家理解。

      注:該比喻來自與網(wǎng)友 ryan0414,看到的時候,不禁驚呼可太貼切了!

      n = 1004

      我們想要計算出小于等于 1004 的非負整數(shù)中,十位上出現(xiàn) 1 的次數(shù)。

      也就是當前位為十位,數(shù)字為 0 時,十位上出現(xiàn) 1 的次數(shù)。

      解析:為什么我們可以直接通過高位數(shù)字 * num,得到 1 出現(xiàn)的次數(shù)

      因為我們高位為 10,可變范圍為 0 ~ 10,但是我們的十位為 0 ,所以高位為 10 的情況取不到,所以共有 10 種情況。

      又當前位為十位,低位共有 1 位,可選范圍為 0 ~ 9 共有 10 種情況,所以直接可以通過 10 * 10 得到。

      其實不難理解,我們可以設(shè)想成行李箱的密碼盤,在一定范圍內(nèi),也就是上面的 0010 ~ 0919 ?, 固定住一位為 1 ,只能移動其他位,看共有多少種組合。

      好啦,這個情況我們已經(jīng)搞明白啦,下面我們看另一種情況。

      n = 1014

      我們想要計算出小于等于 1014 的非負整數(shù)中,十位上出現(xiàn) 1 的次數(shù)。

      也就是當前位為十位,數(shù)字為 1 時,十位上出現(xiàn) 1 的次數(shù)。

      我們在小于 1014 的非負整數(shù)中,十位上為 1 的最小數(shù)字為 10,最大數(shù)字為 1014,所以我們需要在 ?10 ~ 1014 這個范圍內(nèi)固定住十位上的 1 ,移動其他位。

      其實然后我們可以將 1014 看成是 1004 + 10 = 1014

      則可以將 10 ~ 1014 ?拆分為兩部分 0010 ~ 0919 (小于 1004 ),1010 ~ 1014。

      見下圖

      解析:為什么我們可以直接通過 高位數(shù)字 * num + 低位數(shù)字 + 1 ?即 10 * 10 + 4 + 1

      得到 1 出現(xiàn)的次數(shù)

      高位數(shù)字 * num 是得到第一段的次數(shù),第二段為 低位數(shù)字 + 1,求第二段時我們高位數(shù)字和當前位已經(jīng)固定,

      我們可以改變的只有低位。

      可以繼續(xù)想到密碼盤,求第二段時,把前 3 位固定,只能改變最后一位。最后一位最大能到 4 ,那么共有幾種情況?

      n = 1024

      我們想要計算出小于等于 1024 的非負整數(shù)中,十位上出現(xiàn) 1 的次數(shù)。

      也就是當前位為十位,數(shù)字為 2 ~ 9 時,十位上出現(xiàn) 1 的次數(shù)。其中最小的為 0010,最大的為 1019

      我們也可以將其拆成兩段 0010 ~ 0919,1010 ~ 1019

      解析:為什么我們可以直接通過高位數(shù)字 * num + num, 10 * 10 + 10 得到 1 出現(xiàn)的次數(shù)

      第一段和之前所說一樣,第二段的次數(shù),我們此時已經(jīng)固定了高位和當前位,當前位為 1,低位可以隨意取值,上訴例子中,當前位為 10,低位為位數(shù)為 1,則可以取值 0 ~ 9 的任何數(shù),則共有 10 (num) 種可能。

      好啦,這個題目大家應該理解的差不多啦,

      下面我們通過動畫模擬一下,是怎樣一步一步的計算出,小于等于 1014 的數(shù)中 1 出現(xiàn)的次數(shù)。

      注:藍色高位,橙色當前位,綠色低位

      初始化:low = 0, cur = 0, ?num = 1, ?count = 0, ? high = n ;

      好啦,下面我們看一下題目代碼吧

      注:下方代碼沒有簡寫,也都標有注釋,大家可以結(jié)合動畫邊思考邊閱讀。

      題目代碼

      class?Solution?{

      public?int?countDigitOne(int?n)?{

      //高位

      int?high?=?n;

      //低位

      int?low?=?0;

      //當前位

      int?cur?=?0;

      int?count?=?0;

      int?num?=?1;

      while?(high?!=?0)?{

      cur?=?high?%?10;

      high?/=?10;

      //這里我們可以提出?high?*?num?因為我們發(fā)現(xiàn)無論為幾,都含有它

      if?(cur?==?0)?count?+=?high?*?num;

      else?if?(cur?==?1)?count?+=?high?*?num?+?1?+?low;

      else?count?+=?(high?+?1)?*?num;

      //低位

      low?=?cur?*?num?+?low;

      num?*=?10;

      }

      return?count;

      }

      }

      時間復雜度:循環(huán)次數(shù)為數(shù)字 n 的位數(shù),則為 O(logn)

      空間復雜度:O(1)

      推薦閱讀

      《劍指offer》

      Krahets, K 神解析

      好啦,今天就到這吧,拜了個拜,需要一起刷題的同學,可以在小屋內(nèi)點擊刷題小隊。

      數(shù)據(jù)結(jié)構(gòu)

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:為什么我右鍵點擊,沒有出現(xiàn)編劇?為什么沒有刪除行以及調(diào)整行高這些選項?
      下一篇:幻燈片放映怎么自動放下一張(幻燈片怎么手動放映下一張)
      相關(guān)文章
      亚洲乱码中文字幕综合 | 亚洲国产成人久久精品99 | 久久久青草青青国产亚洲免观| 一区二区亚洲精品精华液| 亚洲高清视频免费| 亚洲精品中文字幕无乱码| 亚洲视频一区二区在线观看| 亚洲好看的理论片电影| 亚洲国产二区三区久久| 亚洲av综合avav中文| 亚洲AV无码一区二区三区DV| 国产亚洲成av片在线观看| 国产亚洲综合成人91精品 | 亚洲午夜无码久久久久小说| 亚洲国产系列一区二区三区| 波多野结衣亚洲一级| 国产亚洲精aa在线看| 亚洲色欲啪啪久久WWW综合网| 亚洲人成网站在线在线观看| 亚洲欧美成人一区二区三区| 亚洲成AV人影片在线观看| 国产成人精品亚洲| 亚洲视频一区二区| 美腿丝袜亚洲综合| 国产亚洲婷婷香蕉久久精品 | 亚洲人av高清无码| MM1313亚洲精品无码久久| 国产亚洲精彩视频| 久久精品国产亚洲Aⅴ蜜臀色欲| 久久久久国产成人精品亚洲午夜| 国产亚洲一区二区三区在线不卡| 亚洲永久精品ww47| 亚洲va在线va天堂va四虎| 亚洲神级电影国语版| 亚洲一区欧洲一区| 免费在线观看亚洲| 国产av无码专区亚洲av果冻传媒| 亚洲AV无码第一区二区三区 | 另类图片亚洲校园小说区| 国产国拍亚洲精品福利| 国产亚洲精品a在线无码|