264. Ugly Number II

问题描述

Write a program to find the nth ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.
Note that 1 is typically treated as an ugly number.

思路分析

  1. 首先,丑数序列是由且仅由2、3、5相乘得到的数列。
  2. 一开始我发现,一个新的丑数是已有丑数序列中“还没乘以2的数乘以2”“乘过2还没乘以3的数乘以3”“乘过2、3还没乘以5的数乘以5”中最小的一个。因此想到设立一个pointer数组,来记录每个数是否已经乘了2/3/5,然后每次通过搜索pointer数组来得到“乘过x还没乘以y的数”的下标,从而得到新的丑数。这么做的结果是Time Limit Exceeded,因为每次都要查找pointer数组。其中还有一个需要注意的问题就是数的重复(例如2x3 = 3x2)。
  3. 然后我发现,在“乘过x还没乘以y的数”都有了之后,当选择了一个数后,相应下标加1就是下一个“乘过x还没乘以y的数”的下标。因此我将当n<7时的情况作枚举回答,之后设置初始条件,利用上面的规律解题,效率得以提高,但只能beats 27.36% of Python submissions.
  4. 再然后,发现可以将n<7的情况和其他情况纳入一个规则体系,代码优美了很多。
  5. 最后,我发现我处理相同的数的方法是,如果这次选出来的数和已存在的最后一个数相同,这次循环结果就作废,这导致循环非常冗余。而更好的做法是“得到相同结果的乘数指针”都+1,这样完全消除了冗余。Runtime: 236 ms, which beats 52.12% of Python submissions.

AC代码

#encoding=utf-8
class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        i2 = 0
        i3 = 0
        i5 = 0
        q = [1]
        j = 1
        while j < n:
            m = min(q[i2] * 2, q[i3] * 3, q[i5] * 5)
            if m == q[i2] * 2:
                i2 += 1
            #如果下面两个条件判断用elif,那么后面还需判断m与已有最后一个丑数是否相同,相同则跳过,会增加循环次数。
            if m == q[i3] * 3:
                i3 += 1
            if m == q[i5] * 5:
                i5 += 1
            q.append(m)
            j += 1
        return q[-1]

你可能感兴趣的:(264. Ugly Number II)