劍指Offer(三十一):整數中1出現的次數(從1到n整數中1出現的次數)

劍指Offer(三十一):整數中1出現的次數(從1到n整數中1出現的次數)

搜索微信公衆號:'AI-ming3526'或者'計算機視覺這件小事' 獲取更多算法、機器學習乾貨python

csdn:https://blog.csdn.net/baidu_31657889/git

github:https://github.com/aimi-cn/AILearnersgithub

1、引子

這個系列是我在牛客網上刷《劍指Offer》的刷題筆記,旨在提高下本身的算法能力。
查看完整的劍指Offer算法題解析請點擊CSDN和github連接:
劍指Offer完整習題解析CSDN地址
github地址算法

2、題目

求出1~13的整數中1出現的次數,並算出1~1300的整數中1出現的次數?爲此他特別數了一下1~13中包含1的數字有一、十、十一、十二、13所以共出現5次,可是對於後面問題他就沒轍了。ACMer但願大家幫幫他,並把問題更加廣泛化,能夠很快的求出任意非負整數區間中1出現的次數(從1 到 n 中1出現的次數)。編程

一、思路

方法1:最直觀的是,對於1~n中的每一個整數,分別判斷n中的1的個數,具體見《劍指offer》。這種方法的時間複雜度爲O(N*logN),當N比較大的時候,通常會超時。微信

方法2:這種類別的題目,若是直觀求解不行的話,那麼一般是進行找規律,轉化成一個數學問題。這道題目在《編程之美》上有着比較詳細的描述,下面就結合一個實例進行具體的分析:機器學習

在分析以前,首先須要知道一個規律:學習

  • 從 1 至 10,在它們的個位數中,數字1出現了 1 次。
  • 從 1 至 100,在它們的十位數中,數字1出現了 10 次。
  • 從 1 至 1000,在它們的百位數中,數字1出現了 100 次。
    依此類推,從 1 至 10i,在它們右數第二位中,數字1出現了10 ^ (i - 1)次。

對於 n = 2134,要找到從1 ~ 2134這2134個數字中全部1的個數。咱們能夠對2134進行逐位分析:spa

(1)在個位上,從1~2130,包含213個10,所以數字1出現了213次,剩下的數字213一、213二、213三、2134中個位數上只有2131包含樹脂字1,剩下的都不包含。因此個位數上的數字1的總數爲213 + 1 = 214。.net

(2)在十位上,從1 ~ 2100,包含了21個100,所以數字1出現了21 * 10 = 210次,剩下的數字從2101 ~ 2134,只有2110 ~ 2119這10個數字中十位的數字爲1,因此十位上的數字1的總數爲210 + 10 = 220。

(3)在百位上,從1 ~ 2000,包含了2個1000,所以數字1出現了2 * 100 = 200次,剩下的數字從2001 ~ 2134,只有2100 ~ 2134這35個數字中的百位的數字爲1,因此百位數上數字1的總數爲200 + 35= 235。

(4)在千位上,包含了0個10000,所以數字1出現了0 * 1000 = 0次,剩下的數字中只有1000 ~ 1999這1000個數字中的千位的數字爲1,因此千位上的數字1的總數爲1000。

所以從1 ~ 2134這n個數字中,數字出現的總的次數爲 214 + 220 + 235 +1000 = 1669。

總結一下以上的步驟,能夠獲得這麼一個規律:

對於數字n,計算它的第i(i從1開始,從右邊開始計數)位數上包含的數字1的個數:

假設第i位上的數字爲x的話,則

1.若是x > 1的話,則第i位數上包含的1的數目爲:(高位數字 + 1)* 10 ^ (i-1) (其中高位數字是從i+1位一直到最高位數構成的數字)

2.若是x < 1的話,則第i位數上包含的1的數目爲:(高位數字 )* 10 ^ (i-1)

3.若是x == 1的話,則第i位數上包含1的數目爲:(高位數字) * 10 ^ (i-1) +(低位數字+1) (其中低位數字時從第i - 1位數一直到第1位數構成的數字)

二、編程實現

python

代碼實現方案:

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        if n < 1:
            return 0
        # mult位數 sumTime出現1的次數和
        mult, sumTimes = 1, 0
        while n//mult:
            div, mod = divmod(n, mult*10)
            curNum, curMod = divmod(mod, mult)
            if curNum > 1:
                sumTimes += div*mult + mult
            elif curNum == 1:
                sumTimes += div*mult + curMod + 1
            else:
                sumTimes += div*mult
            mult = mult*10
        return sumTimes複製代碼

AIMI-CN AI學習交流羣【1015286623】 獲取更多AI資料

分享技術,樂享生活:咱們的公衆號計算機視覺這件小事每週推送「AI」系列資訊類文章,歡迎您的關注!

相關文章
相關標籤/搜索