【面试题49 丑数】
我们把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
Leetcode题目对应位置: 面试题49:丑数
思路:动态规划。
丑数的递推性质:丑数 = 某个较小丑数 x 某因子(2/3/5)
因此在求解第 k
个丑数时,只需要求得前面的丑数中,分别乘2、乘3、乘5 后最小的一个即可。比如现在已知前 3 个丑数,求第 4 个丑数:
x1 | x2 | x3 | x4 |
---|---|---|---|
1 | 2 | 3 | ? |
用 3 个指针 a、b、c 分别用来代表乘2、乘3、乘5,初始时都指向 x1。
求 x2:
x
a
∗
2
=
2
x_a * 2 = 2
xa∗2=2,
x
b
∗
3
=
3
x_b * 3 = 3
xb∗3=3,
x
c
∗
5
=
5
x_c * 5 = 5
xc∗5=5,最小的大于
x
1
x_1
x1 的值是
x
a
∗
2
=
2
x_a * 2 = 2
xa∗2=2,所以
x
2
=
2
x_2 = 2
x2=2,a 向后移动一个位置,指向 x2
求 x3:
x
a
∗
2
=
4
x_a * 2 = 4
xa∗2=4,
x
b
∗
3
=
3
x_b * 3 = 3
xb∗3=3,
x
c
∗
5
=
5
x_c * 5 = 5
xc∗5=5,最小的大于
x
2
x_2
x2 的值是
x
b
∗
3
=
3
x_b * 3 = 3
xb∗3=3,所以
x
3
=
3
x_3 = 3
x3=3,b 向后移动一个位置,指向 x3
求 x3:
x
a
∗
2
=
4
x_a * 2 = 4
xa∗2=4,
x
b
∗
3
=
6
x_b * 3 = 6
xb∗3=6,
x
c
∗
5
=
5
x_c * 5 = 5
xc∗5=5,最小的大于
x
3
x_3
x3 的值是
x
a
∗
2
=
4
x_a * 2 = 4
xa∗2=4,所以
x
4
=
4
x_4 = 4
x4=4,a 向后移动一个位置,指向 x4
在指针移动过程中,从 a、b、c 中选择一个乘积大于当前丑数的最小值,然后移动选中的指针,其余指针保持不变。
时间复杂度:O(n)
空间复杂度:O(n),创建额外的 dp 数组
class Solution:
def nthUglyNumber(self, n: int) -> int:
if n == 1: return 1
a = b = c = 0
dp = [1 for _ in range(n)]
for i in range(1, n):
t2, t3, t5 = dp[a]*2, dp[b]*3, dp[c]*5
dp[i] = min(t2, t3, t5)
if dp[i] == t2: a += 1
if dp[i] == t3: b += 1
if dp[i] == t5: c += 1
return dp[-1]