【中等】力扣算法题解析LeetCode264:丑数 II

关注文末推广名片,即可免费获得本题测试源码

题目来源:LeetCode264:丑数 II

问题抽象: 给定整数 n,要求生成 n 个丑数(质因数仅含 235 的正整数,按升序排列),需满足以下核心需求:

  1. 丑数序列定义

    • 起始值1 为第一个丑数;
    • 生成规则:后续丑数由已有丑数 ×2×3×5 生成(如 1→2→3→4→5→6→8→...);
    • 去重排序:新数需去重并按升序加入序列。
  2. 输入约束

    • n ∈ [1, 1690](序列最大索引为 1690);
    • 需处理 大索引值(如 n=1690 对应丑数 2123366400)。
  3. 计算要求

    • 时间复杂度 O(n)(动态规划 + 三指针);
    • 空间复杂度 O(n)(存储前 n 个丑数);
    • 禁止暴力枚举(因数值范围极大)。
  4. 关键策略

    • 三指针法
      • 指针 p2p3p5 分别标记 ×2×3×5 的基准丑数索引;
      • 每次取 min(dp[p2]*2, dp[p3]*3, dp[p5]*5) 作为新丑数,并更新对应指针。
  5. 边界处理

    • n=1 时返回 1
    • 序列无重复值(如 6=2×3=3×2 仅计数一次);
    • 示例:
      • n=78(序列:[1,2,3,4,5,6,8]);
      • n=1012

输入:整数 n(如 10
输出:第 n 个丑数(如 12)。


解题思路

核心思想:动态规划 + 三指针

  1. 定义状态

    • 使用数组 dp 存储丑数序列,dp[0] = 1(第1个丑数为1)。
    • 初始化三个指针 p2, p3, p5,分别指向下一个可能通过乘以 2、3、5 得到新丑数的位置。
  2. 状态转移

    • 对于每个位置 i(从 1 到 n-1),计算候选丑数:
      next2 = dp[p2] * 2
      next3 = dp[p3] * 3
      next5 = dp[p5] * 5
    • dp[i] 取三者中的最小值,确保丑数序列有序递增。
    • 更新指针:哪个指针生成了当前最小丑数,该指针后移一位(若多个指针生成相同值,则同时后移,避免重复)。
  3. 终止条件

    • 填充完 dp[0]dp[n-1] 后,返回 dp[n-1]

时间复杂度 O(n):只需遍历一次数组。 空间复杂度 O(n):使用额外数组存储丑数序列。 避免重复计算:通过指针独立移动,每个丑数只生成一次。


代码实现(Java版)🔥点击下载源码

class Solution {
    public int nthUglyNumber(int n) {
        // 初始化丑数序列
        int[] dp = new int[n];
        dp[0] = 1; // 第一个丑数是1
        
        // 初始化三个指针,分别指向乘以2、3、5的下一个候选位置
        int p2 = 0, p3 = 0, p5 = 0;
        
        for (int i = 1; i < n; i++) {
            // 计算三个指针指向的候选丑数
            int next2 = dp[p2] * 2;
            int next3 = dp[p3] * 3;
            int next5 = dp[p5] * 5;
            
            // 取最小值作为下一个丑数
            dp[i] = Math.min(next2, Math.min(next3, next5));
            
            // 更新生成当前丑数的指针(多个同时生成则同时更新)
            if (dp[i] == next2) p2++;
            if (dp[i] == next3) p3++;
            if (dp[i] == next5) p5++;
        }
        
        return dp[n - 1];
    }
}

代码说明

  1. 初始化

    • dp[0] = 1 表示第一个丑数为 1。
    • 指针 p2, p3, p5 初始指向位置 0。
  2. 循环生成丑数i 从 1 到 n-1):

    • 计算候选值:根据当前指针位置计算 next2, next3, next5
    • 确定最小丑数:取三个候选值的最小值放入 dp[i]
    • 更新指针:若当前丑数由某个指针生成,则该指针后移(可能同时更新多个指针,避免重复值)。
  3. 返回结果

    • 循环结束后,dp[n-1] 即为第 n 个丑数。

提交详情(执行用时、内存消耗)在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值