<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我可太喜歡這個(gè)題了

          共 3278字,需瀏覽 7分鐘

           ·

          2021-05-19 13:44

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

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

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

          題目描述

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

          示例 1:

          輸入:n = 13 輸出:6

          示例 2:

          輸入:n = 0 輸出:0

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

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

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

          嗯,很棒的方法,可惜會(huì)超時(shí)。

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

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

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

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

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

          4025d64d8334d61d7114e9b66c4b2907.webp

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

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

          見下圖

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

          c151a8360aaf9449de9ef7d4c742409f.webp

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

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

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

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

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

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

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

          b7f10fa532dad90ba83570f5dc99a15f.webp

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

          我們稱之為當(dāng)前位。num 則代表當(dāng)前位的位因子,當(dāng)前位為個(gè)位時(shí) num = 1,十位時(shí)為 10,百位時(shí)為 100....

          那我們將當(dāng)前位左邊的定義為高位,當(dāng)前位右邊的定義位低位

          例:n = 1004 ,此時(shí)指針指向十位(當(dāng)前位)num = 10,高位為百位,千位,低位為個(gè)位

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

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

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

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

          n = 1004

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

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

          684cda452495d551d72adaf57826b993.webp

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

          因?yàn)槲覀兏呶粸?10,可變范圍為 0 ~ 10,但是我們的十位為 0 ,所以高位為 10 的情況取不到,所以共有 10 種情況。

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

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

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

          n = 1014

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

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

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

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

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

          見下圖

          e884de82d6372369a72b9be67f7eb6ed.webp

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

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

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

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

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

          n = 1024

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

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

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

          846c23d64f7af45d1ec4a7d65ce89197.webp

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

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

          好啦,這個(gè)題目大家應(yīng)該理解的差不多啦,

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

          注:藍(lán)色高位,橙色當(dāng)前位,綠色低位

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



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

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

          題目代碼

          class?Solution?{
          ????public?int?countDigitOne(int?n)?{
          ????????//高位
          ????????int?high?=?n;
          ????????//低位
          ????????int?low?=?0;
          ????????//當(dāng)前位
          ????????int?cur?=?0;
          ????????int?count?=?0;
          ????????int?num?=?1;
          ????????while?(high?!=?0)?{
          ????????????cur?=?high?%?10;
          ????????????high?/=?10;
          ????????????//這里我們可以提出?high?*?num?因?yàn)槲覀儼l(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;
          ????}
          }

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

          空間復(fù)雜度:O(1)

          推薦閱讀

          • 《劍指offer》

          • ? Krahets, K 神解析

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

          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  我要看一级黄色视频 | 超清无码在线网上 | 丁香五月天婷婷婷 | 神马午夜国产福利 | 高颜值呻吟给力 |