1. 程式人生 > 實用技巧 >劍指 Offer 43. 1~n整數中1出現的次數

劍指 Offer 43. 1~n整數中1出現的次數

  • 題目描述
輸入一個整數 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