Ugly Number II

题目描述

Write a program to find the n-th 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.

解题方法

丑陋数序列可以拆分为下面3个子列表:

(1) 1×2, 2×2, 3×2, 4×2, 5×2, …
(2) 1×3, 2×3, 3×3, 4×3, 5×3, …
(3) 1×5, 2×5, 3×5, 4×5, 5×5, …

我们可以发现每一个子列表都是丑陋数本身(1, 2, 3, 4, 5, …) 乘以 2, 3, 5

接下来我们使用与归并排序相似的合并方法,从3个子列表中获取丑陋数。每一步我们从中选出最小的一个,然后向后移动一步。

三个指针p2,p3,p5分别代表下一次乘以2,3,5的来比较ugly number的index,如果用过了就指向下一个ugly number

Solution

一开始错误的作法!

class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n < 0:
            return -1

        if n == 1:
            return 1
        p = 1
        result = [1]
        p2, p3, p5 = 0, 0, 0
        while p < n:
            m2 = result[p2] * 2
            m3 = result[p3] * 3
            m5 = result[p5] * 5
            m = min(m2, m3, m5)
            result.append(m)
            if m == m2:
                p2 += 1
            elif m == m3:
                p3 += 1
            elif m == m5:
                p5 += 1
            p += 1
        return result[-1]

这种做法是错误的,因为m2,m3,m5可能会有相同的,会导致重复的数重复加到数组内,其实应该跳过 比如n等于7时

2 3 5  n = 2
2
4 3 5  n =3
3
4 6 5  n = 4
4
6 6 5  n = 5
5
6 6 10  n = 6
6
8 6 10  n = 7
6

可以看到当m2,m3的指向的数分别乘以2,3时,得到的都是6,6只能加到数组中一次,所以应该对它们都跳过!!

正确的作法

class Solution(object):
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n < 0:
            return -1

        if n == 1:
            return 1
        p = 1
        result = [1]
        p2, p3, p5 = 0, 0, 0
        while p < n:
            m2 = result[p2] * 2
            m3 = result[p3] * 3
            m5 = result[p5] * 5
            m = min(m2, m3, m5)
            result.append(m)
            if m == m2:
                p2 += 1
            if m == m3:
                p3 += 1
            if m == m5:
                p5 += 1
            p += 1
        return result[-1]

Reference