劍指 Offer 43. 1~n整數中1出現的次數
阿新 • • 發佈:2020-08-27
- 題目描述
輸入一個整數 n ,求1~n這n個整數的十進位制表示中1出現的次數。 例如,輸入12,1~12這些整數中包含1 的數字有1、10、11和12,1一共出現了5次。 示例 1: 輸入:n = 12 輸出:5 示例 2: 輸入:n = 13 輸出:6 限制: 1 <= n <2^31
- 解答
這道題的考點就是:找規律!
思路呢首先需要回憶下我們平時旅行箱上用的密碼鎖,或者1分鐘跳繩用的繩子的計數器。
將1~n的個位、十位、百位、...的1出現次數相加,即為1出現的總次數。
那麼我們其實可以想象假如固定某一數位為1,求其他數位的全排列。
再看看,假如要求n=2304,求十位為1的出現次數:
我們可以將這個數分成:
高位:high
當前位:cur
低位:low
位因子:10 ^k (k=0,...m)
此時對於2304,1在十位出現的範圍為:0010~2219
固定十位的1,那麼其他位的排列則為0~229,有230個數(可以湊為公式high * digit)
但此時cur是為0的,那麼假如說這個數是2314,假設同樣求1在十位的次數,那情況是怎樣的呢?
此時high=23,low=4,cur=1,
那麼1出現的範圍則是0010~2314
此時1在十位出現的次數為000~234,有235個數(同樣湊個公式為high*digit + low + 1)
那麼假如這個數時2324,此時cur>1,會是怎麼樣?
此時high = 23,low= 4, cur=2
那麼1出現的範圍是0010~2319
此時1在十位出現的次數為000~239,有240個數(再湊個公式為(high+1) * digit)
那麼這樣看的話,思路是不是就很清晰了。但是還是要注意高位的移動,當前位的移動和低位的移動。迴圈的結束條件是:當高位為0和當前位均為0,說明當前位已經越過最大數的左邊界了。
class Solution: def countDigitOne(self, n: int) -> int: digit = 1 #初始位因子 cur = n % 10 #初始當前位 high= n // 10 #初始高位 low = 0 #初始低位 res = 0 while high != 0 or cur != 0: if cur == 1: res += high * digit + low + 1 elif cur == 0: res += high * digit else: res += (high + 1) * digit low = low + cur * digit #低位向左移動 cur = high % 10 #當前位向左移動 high = high // 10 #高位向左移動 digit *= 10 return res