劍指offer:醜數

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

# -*- 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()
相關文章
相關標籤/搜索