《劍指 Offer (第 2 版)》第 43 題:整數(shù)中 1 出現(xiàn)的次數(shù)(從 1 到 n 整數(shù)中 1 出現(xiàn)的次數(shù))

第 43 題:整數(shù)中 1 出現(xiàn)的次數(shù)(從 1 到 n 整數(shù)中 1 出現(xiàn)的次數(shù))

傳送門:AcWing:從 1 到 n 整數(shù)中 1 出現(xiàn)的次數(shù)薇缅。

輸入一個整數(shù) n眯亦,求從 1nn 個整數(shù)的十進(jìn)制表示中 1 出現(xiàn)的次數(shù)。

例如輸入 12就缆,從 112 這些整數(shù)中包含 1 的數(shù)字有 1101112晒来,“1” 一共出現(xiàn)了 5 次。

樣例:

輸入: 12
輸出: 5

同 LeetCode 第 233 題:數(shù)字 1 的個數(shù)郑现。

大雪菜的解法:

C++ 代碼:

《劍指 Offer (第 2 版)》第 43 題:整數(shù)中 1 出現(xiàn)的次數(shù)(從 1 到 n 整數(shù)中 1 出現(xiàn)的次數(shù))-1

思路:

《劍指 Offer (第 2 版)》第 43 題:整數(shù)中 1 出現(xiàn)的次數(shù)(從 1 到 n 整數(shù)中 1 出現(xiàn)的次數(shù))-2

Python 代碼:

# 56. 從1到n整數(shù)中1出現(xiàn)的次數(shù)
#
# 輸入一個整數(shù)n,求從1到n這n個整數(shù)的十進(jìn)制表示中1出現(xiàn)的次數(shù)。
#
# 例如輸入12冠骄,從1到12這些整數(shù)中包含“1”的數(shù)字有1片排,10,11和12辛友,其中“1”一共出現(xiàn)了5次薄扁。
#
# 樣例
# 輸入: 12
# 輸出: 5
class Solution(object):
    def numberOf1Between1AndN_Solution(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n <= 0:
            return 0

        number = []
        while n:
            number.append(n % 10)
            n //= 10

        res = 0
        for i in range(len(number) - 1, -1, -1):
            left = 0
            right = 0
            # 想清楚這里 t 為什么從 1 開始
            t = 1
            for j in range(len(number) - 1, i, -1):
                left = left * 10 + number[j]

            for j in range(i - 1, -1, -1):
                right = right * 10 + number[j]
                t *= 10
            # print(left, right)
            # 至少有左邊的數(shù)這么多
            res += left * t
            # print(number[i], left, right, t, left * t)
            if number[i] == 1:
                res += right + 1
            elif number[i] > 1:
                res += t
        return res


if __name__ == '__main__':
    solution = Solution()
    n = 45032
    result = solution.numberOf1Between1AndN_Solution(n)
    print('result', result)

解法1:從 1n 遍歷,每個數(shù)通過對 10 求余數(shù)判斷整數(shù)的個位數(shù)字是不是 1废累,大于 10 的除以 10 之后再判斷邓梅。我們對每個數(shù)字都要做除法和求余運(yùn)算以求出該數(shù)字中 1 出現(xiàn)的次數(shù)。如果輸入數(shù)字 n邑滨,nO(\log n) 位日缨,我們需要判斷每一位是不是 1,那么時間復(fù)雜度為 O(n* \log n)驼修。這樣做殿遂,計(jì)算量大,效率不高乙各。

本文采用《數(shù)學(xué)之美》上面提出的方法墨礁,設(shè)定整數(shù)點(diǎn)(如 110耳峦、100等等)作為位置點(diǎn)i(對應(yīng) n的個位恩静、十位、百位等等)蹲坷,分別對每個數(shù)位上有多少包含 1 的點(diǎn)進(jìn)行分析驶乾。

根據(jù)設(shè)定的整數(shù)位置,對 n 進(jìn)行分割循签,分為兩部分级乐,高位 n/i,低位 n \% i县匠;

1风科、當(dāng) i 表示百位撒轮,且百位對應(yīng)的數(shù) \ge2

例如 n=31456贼穆,此時考慮 i=100题山,則 a=314b=56故痊。

此時百位為 1 的次數(shù)有 a/10+1=32 批次顶瞳,具體如下:

說明:第 1 批次:00100-00199,一共 100 個數(shù)愕秫;

第 2 批次:01100-01199慨菱,一共 100 個數(shù);

……

第 32 批次:31100-31199豫领,一共 100 個數(shù)抡柿;

最高兩位 0-31,每一批次都包含 100 個連續(xù)的點(diǎn)等恐,即共有 (a/10+1)\times100 個點(diǎn)的百位為 1洲劣;

2、當(dāng) i 表示百位课蔬,且百位對應(yīng)的數(shù)為 1囱稽,

例如 n=31156i=100二跋,則 a=311战惊,b=56,此時百位對應(yīng)的就是 1扎即。

第 1 批次:00100-00199吞获,一共 100 個數(shù);

第 2 批次:01100-01199谚鄙,一共 100 個數(shù)各拷;

……

第 31 批次:30100-30199,一共 100 個數(shù)闷营;

第 32 批次:31100-311569烤黍,一共 57 個數(shù);

則共有 a/10 次是包含 100 個連續(xù)點(diǎn)傻盟,最高兩位 0-30速蕊。

當(dāng)最高兩位為 31(即 a=311),本次只對應(yīng)局部點(diǎn) 00-56娘赴,共 b+1次规哲,所有點(diǎn)加起來共有 (a/10\times100)+(b+1),這些點(diǎn)百位對應(yīng)為 1;

3诽表、當(dāng) i 表示百位媳叨,且百位對應(yīng)的數(shù)為 0腥光,如 n=31056i=100糊秆,則 a=310b=56议双。

第 1 批次:00100-00199痘番,一共 100 個數(shù);

第 2 批次:01100-01199平痰,一共 100 個數(shù)汞舱;

……

第 31 批次:30100-30199,一共 100 個數(shù)宗雇;

第 32 批次:31000-31056昂芜,一共 0 個數(shù);

此時百位為 1 的次數(shù)有 a/10=31赔蒲,最高兩位 0-30泌神;

綜合以上 3 種情況,當(dāng)百位對應(yīng) 0\ge2 時舞虱,有 (a+8)/10 次包含所有 100 個點(diǎn)欢际,還有當(dāng)百位為 1a\%10==1),需要增加局部點(diǎn) b+1矾兜。

之所以補(bǔ) 8损趋,是因?yàn)楫?dāng)百位為 0,則 a/10==(a+8)/10椅寺,當(dāng)百位 \ge2浑槽,補(bǔ) 8 會產(chǎn)生進(jìn)位,效果等同于 (a/10+1)返帕。

Python 代碼:

class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        count = 0
        i = 1
        while i <= n:
            a = n / i
            b = n % i
            count += (a+8) / 10 * i + (a % 10 == 1)*(b + 1)
            i *= 10
        return count

參考資料:https://blog.csdn.net/qq_38211852/article/details/80863364

https://cuijiahua.com/blog/2017/12/basis_31.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末桐玻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子溉旋,更是在濱河造成了極大的恐慌畸冲,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件观腊,死亡現(xiàn)場離奇詭異邑闲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)梧油,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門苫耸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人儡陨,你說我怎么就攤上這事褪子×刻剩” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵嫌褪,是天一觀的道長呀枢。 經(jīng)常有香客問我,道長笼痛,這世上最難降的妖魔是什么裙秋? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮缨伊,結(jié)果婚禮上摘刑,老公的妹妹穿的比我還像新娘。我一直安慰自己刻坊,他們只是感情好枷恕,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谭胚,像睡著了一般徐块。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上漏益,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天蛹锰,我揣著相機(jī)與錄音,去河邊找鬼绰疤。 笑死铜犬,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的轻庆。 我是一名探鬼主播癣猾,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼余爆!你這毒婦竟也來了纷宇?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤蛾方,失蹤者是張志新(化名)和其女友劉穎像捶,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桩砰,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拓春,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了亚隅。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硼莽。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖煮纵,靈堂內(nèi)的尸體忽然破棺而出懂鸵,到底是詐尸還是另有隱情偏螺,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布匆光,位于F島的核電站套像,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏终息。R本人自食惡果不足惜凉夯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望采幌。 院中可真熱鬧,春花似錦震桶、人聲如沸休傍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽磨取。三九已至,卻和暖如春柴墩,著一層夾襖步出監(jiān)牢的瞬間忙厌,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工江咳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逢净,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓歼指,卻偏偏與公主長得像爹土,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踩身,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容