题目描述
我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
思路分析
这道题实际上是leetcode主站的丑数2。
暴力会超时啊,我试过了哈哈,测试用例都直接超时了。
动规开始!
首先递推思想,某个丑数一定是由比他小的丑数 乘以2或3或5得到的。
且丑数需要从小到大排列,所以也就是说,当前丑数‘x‘乘以2或3或5 中的最小值就是下一个丑数。
//下一个最小的丑数一定在n2,n3,n5中。
n2 = dp[a]*2
n3 = dp[b]*3
n5 = dp[c]*5
进而可得到递推公式:dp[i] = min(前一个丑数 * 2,前一个丑数 * 3 ,前一个丑数 * 5)
dp[i] = min(n2,n3,n5)
因此,可设置指针 a,b,c 指向首个丑数(即 1 ),循环根据递推公式得到下个丑数,并每轮将对应指针执行 +1 即可。
这块有一个细节需要注意,比如 2和3这俩分别由a和b指着,2 * 3 和3 * 2都是6。所以a和b指针都需要向后挪动。
//看看刚得到的最小丑数是n2还是n3还是n5。对应指针需要加1
if dp[i] == n2:
a+=1
if dp[i] == n3:
b+=1
if dp[i] == n5:
c+=1
这里设置三个指针的思想,可以想象成分别代表 * 2 * 3 * 5,当某个数被使用过了,则对应指针就往后挪动,表示已经考虑过该数的对应乘积了。
开始:
1.初始化dp含义:
dp[i]表示 第i+1个丑数
2.递推公式:
dp[i]=min(dp[a]×2,dp[b]×3,dp[c]×5)
3.初始化dp数组:
显然 dp[0] = 1
完整代码
class Solution:
def nthUglyNumber(self, n: int) -> int:
#dp[i] 表示 第i+1个丑数
dp = [0] * n
dp[0] = 1
a =b=c = 0
for i in range(1,n):
n2 = dp[a]*2
n3 = dp[b]*3
n5 = dp[c]*5
dp[i] = min(n2,n3,n5)
if dp[i]==n2:
a+=1
if dp[i] == n3:
b+=1
if dp[i] == n5:
c+=1
return dp[-1]