264. 丑数 II - 力扣(LeetCode)

题目:

        给你一个整数 n ,请你找出并返回第 n丑数

        丑数 就是质因子只包含 235 的正整数。

示例 1:

输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。

示例 2:

输入:n = 1
输出:1
解释:1 通常被视为丑数。

提示:

  • 1 <= n <= 1690


思路如下:

        要求第 n 个丑数,我们从第一个开始。丑数 就是质因子只包含 235 的正整数,所以生成的链表的每个丑数都可以表示为2的倍数/3的倍数/5的倍数 。但问题是链表从左到右数字逐渐变大,因此要确定每次需要 × 2/3/5 的哪一个数字才能获得最小丑数。

        这里运用动态规划的方法:用没有乘过 2 的最小丑数乘 2;没有乘过 3 的最小丑数乘 3;没有乘过 5 的最小丑数乘 5。在得到的数字中取最小,即为新的丑数。


题解如下:

class Solution:
 def nthUglyNumber(self, n: int) -> int:
     # 初始化一个长度为n的数组dp,所有元素初始为1,dp[i]表示第i+1个丑数
     dp = [1] * n
     # 初始化三个指针p2、p3、p5,分别对应质因数2、3、5的起始位置,初始都指向第0个元素
     p2, p3, p5 = 0, 0, 0
​
     # 从第1个位置(即第2个丑数)开始填充dp数组,直到第n-1个位置(即第n个丑数)
     for i in range(1, n):
         # 计算当前三个可能的丑数候选值
         cnt2, cnt3, cnt5 = dp[p2] * 2, dp[p3] * 3, dp[p5] * 5
​
         # 取三个候选值中的最小值作为当前的丑数
         dp[i] = min(cnt2, cnt3, cnt5)
​
         # 根据当前丑数的来源,更新对应的指针
         if dp[i] == cnt2:
             p2 += 1  # 如果当前丑数来自2的倍数,则移动p2指针
         if dp[i] == cnt3:
             p3 += 1  # 如果当前丑数来自3的倍数,则移动p3指针
         if dp[i] == cnt5:
             p5 += 1  # 如果当前丑数来自5的倍数,则移动p5指针
​
     # 返回第n个丑数,即dp数组的最后一个元素
     return dp[-1]

题解示例:

​
假设n=10,代码的执行过程如下:
​
初始化:
    dp = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    p2=0, p3=0, p5=0
​
生成第2个丑数(索引1):
    cnt2=1*2=2, cnt3=1*3=3, cnt5=1*5=5
    dp[1] = min(2,3,5) = 2
    更新p2为1
​
生成第3个丑数(索引2):
    cnt2=2*2=4, cnt3=1*3=3, cnt5=1*5=5
    dp[2] = min(4,3,5) = 3
    更新p3为1
​
生成第4个丑数(索引3):
    cnt2=2*2=4, cnt3=3*3=9, cnt5=1*5=5
    dp[3] = min(4,9,5) = 4
    更新p2为2
​
生成第5个丑数(索引4):
    cnt2=4*2=8, cnt3=3*3=9, cnt5=1*5=5
    dp[4] = min(8,9,5) = 5
    更新p5为1
​
生成第6个丑数(索引5):
    cnt2=4*2=8, cnt3=3*3=9, cnt5=5*5=25
    dp[5] = min(8,9,25) = 8
    更新p2为3
​
生成第7个丑数(索引6):
    cnt2=8*2=16, cnt3=3*3=9, cnt5=5*5=25
    dp[6] = min(16,9,25) = 9
    更新p3为2
​
生成第8个丑数(索引7):
    cnt2=8*2=16, cnt3=9*3=27, cnt5=5*5=25
    dp[7] = min(16,27,25) = 16
    更新p2为4
​
生成第9个丑数(索引8):
    cnt2=16*2=32, cnt3=9*3=27, cnt5=5*5=25
    dp[8] = min(32,27,25) = 25
    更新p5为2
​
生成第10个丑数(索引9):
    cnt2=16*2=32, cnt3=9*3=27, cnt5=25*5=125
    dp[9] = min(32,27,125) = 27
    更新p3为3
​
最终,dp数组为[1, 2, 3, 4, 5, 8, 9, 16, 25, 27],返回dp[-1]即第10个丑数27。
​

逻辑梳理:

  1. 初始化

    • dp数组用于存储生成的丑数序列,dp[0]初始化为1(第一个丑数)。

    • p2p3p5三个指针分别对应质因数2、3、5的当前候选位置,初始都指向第一个丑数(索引0)。

  2. 生成丑数

    • 从第2个丑数(索引1)开始,每次生成新的丑数时,计算三个可能的候选值(当前指针所指丑数分别乘以2、3、5)。

    • 取这三个候选值中的最小值作为当前的丑数,并存入dp数组。

    • 根据当前丑数的来源(即它等于哪个候选值),移动对应的指针到下一个位置。

  3. 返回结果

    • 当循环结束时,dp数组的最后一个元素即为第n个丑数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值