题目描述
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数
示例:
输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。
解题思路:
每个丑数都是由2,3,5相乘得到的,如果已经得到
n
−
1
n - 1
n−1个数,则第
n
n
n个数可以由前面的数得到,并且是有一定规律的,本题属于动态规划。
我们即第n个数为
L
n
L_n
Ln,则有
L
n
=
m
i
n
(
L
a
∗
2
,
L
b
∗
3
,
L
c
∗
5
)
,
a
,
b
,
c
≤
n
−
1
L_n = min(L_a * 2, L_b * 3, L_c * 5), a,b,c \leq n -1
Ln=min(La∗2,Lb∗3,Lc∗5),a,b,c≤n−1
且
a
,
b
,
c
a, b, c
a,b,c满足
f
(
x
)
=
{
L
a
×
2
>
x
n
≥
L
a
−
1
×
2
L
b
×
3
>
x
n
≥
L
b
−
1
×
3
L
c
×
5
>
x
n
≥
L
c
−
1
×
5
f(x)=\left\{ \begin{aligned} L_a \times2 > x_n \geq L_{a-1} \times 2 \\ L_b \times3 > x_n \geq L_{b-1} \times 3 \\ L_c \times5 > x_n \geq L_{c-1} \times 5 \end{aligned} \right.
f(x)=⎩⎪⎨⎪⎧La×2>xn≥La−1×2Lb×3>xn≥Lb−1×3Lc×5>xn≥Lc−1×5
也就是
L
a
×
2
L_a \times 2
La×2是第一个乘
2
2
2之后大于
L
n
L_n
Ln的丑数,所以,
a
a
a可以按递增的顺序,同理
b
,
c
b, c
b,c也可按递增的顺序得到。
假设:
状态定义,设动态规划列表为
L
n
L_n
Ln,
L
i
L_i
Li表示第
i
+
1
i + 1
i+1个丑数。索引
a
,
b
,
c
a, b, c
a,b,c指向
L
n
L_n
Ln第1个数,
L
0
=
1
L_0 = 1
L0=1
转移方程: 每次得到
L
i
L_i
Li之后,索引
a
,
b
,
c
a, b, c
a,b,c都需要更新。
L
i
L_i
Li由
L
a
L_a
La,
L
b
L_b
Lb,
L
c
L_c
Lc哪个得到,则相应的下标
+
1
+1
+1,指向下一个数。
初始状态:
L
0
=
1
L_0 = 1
L0=1
返回值:
L
n
−
1
L_{n-1}
Ln−1
代码:
class Solution(object):
def nthUglyNumber(self, n):
"""
:type n: int
:rtype: int
"""
if n == 1: return 1
listn, a, b, c = [1] * n, 0, 0, 0
for i in range(1, n):
n2, n3, n5 = listn[a] * 2, listn[b] * 3, listn[c] * 5
listn[i] = min(n2, n3, n5)
if listn[i] == n2: a += 1
if listn[i] == n3: b += 1
if listn[i] == n5: c += 1
# print(listn)
return listn[i]