劍指offer:醜數

題目描述
把只包含質因子2、3和5的數稱作醜數(Ugly Number)。例如6、8都是醜數,但14不是,因爲它包含質因子7。 習慣上我們把1當做是第一個醜數。求按從小到大的順序的第N個醜數。

# -*- coding: utf-8 -*-
# @Time         : 2019-07-11 23:24
# @Author       : Jayce Wong
# @ProjectName  : job
# @FileName     : getUglyNumber.py
# @Blog         : https://blog.51cto.com/jayce1111
# @Github       : https://github.com/SysuJayce

class Solution:
    """
    題目中醜數的定義是隻包含因子2,3,5的數,特別地,1是第一個醜數。

    解法1:
    從1開始,逐個判斷每個數字是不是醜數,如果是,則計數器加一,直到找到所要求的第n個醜數爲止。
    但是這樣做的話會對很多非醜數進行計算,時間複雜度太高。

    解法2:
    定義一個數組,用於按順序保存已經找到的醜數,再定義三個指針p2, p3, p5,其中p2指向數組中第一個
    乘以2之後會比當前數組中末尾元素要大的數字;p3和p5同理。這樣,當p2 * 2之後就會比當前最後一個
    醜數要大,而當p3 * 3 之後也會比最後一個醜數要大, p5同理。這樣,當前最後一個醜數之後的第一個
    醜數就出現在p2 * 2, p3 * 3, p5 * 5之間,我們只需要比較這三個數的大小即可找到下一個醜數。
    注意每找到一個這樣的醜數之後我們就要更新p2, p3, p5,直到我們找到足夠多的醜數。
    這種方法是以空間換時間,我們維護了一個長度爲n的數組,並最終返回這個數組的末尾元素。
    """
    def GetUglyNumber_Solution(self, index):
        if index <= 0:
            return 0

        uglyNumbers = [1] * index  # 用於保存已找到醜數的數組
        p2 = p3 = p5 = 0
        idx = 1

        while idx < index:
            # 每次都這三個數中找一個最小的作爲下一個醜數
            nextUglyNumber = min(uglyNumbers[p2] * 2,
                                 uglyNumbers[p3] * 3,
                                 uglyNumbers[p5] * 5)
            uglyNumbers[idx] = nextUglyNumber

            # 然後更新這三個指針
            while uglyNumbers[p2] * 2 <= nextUglyNumber:
                p2 += 1
            while uglyNumbers[p3] * 3 <= nextUglyNumber:
                p3 += 1
            while uglyNumbers[p5] * 5 <= nextUglyNumber:
                p5 += 1

            idx += 1

        return uglyNumbers[index - 1]

def main():
    solution = Solution()
    index = 1
    print(solution.GetUglyNumber_Solution(index))

if __name__ == '__main__':
    main()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章