【动态规划】49题-丑数

1 题目描述

我们把只包含质因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。
示例:

输入: n = 10
输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

说明:

1 是丑数。
n 不超过1690。

2 解题思路

动态规划

解题思路:

丑数的递推性质:丑数只包含因子2,3,5,因此有“ 丑 数 = 某 较 小 丑 数 × 某 因 子 丑数=某较小丑数\times某因子 =×”(例如: 10 = 5 × 2 10=5\times2 10=5×2)。

设已知长度为n的丑数序列 x 1 , x 2 , . . . , x n x_1,x_2,...,x_n x1,x2,...,xn,求第n+1个丑数 x n + 1 x_{n+1} xn+1。根据递推性质,丑数 x n + 1 x_{n+1} xn+1只可能是以下三种情况之一(索引a,b,c为未知数):
x n + 1 = { x a × 2 a ∈ [ 1 , n ] x b × 3 b ∈ [ 1 , n ] x c × 5 c ∈ [ 1 , n ] x_{n+1}=\left\{ \begin{array}{lcl} x_a\times2 & & {a\in[1,n]}\\ x_b\times3 & & {b\in[1,n]}\\ x_c\times5 & & {c\in[1,n]} \end{array} \right. xn+1=xa×2xb×3xc×5a[1,n]b[1,n]c[1,n]

由于 x n + 1 x_{n+1} xn+1是最接近 x n x_n xn的丑数。因此索引a,b,c需满足以下条件:
{ x a × 2 > x n ≥ x a − 1 × 2 即 x a 为 首 个 乘 以 2 后 大 于 x n 的 丑 数 x b × 3 > x n ≥ x b − 1 × 3 即 x b 为 首 个 乘 以 3 后 大 于 x n 的 丑 数 x c × 5 > x n ≥ x c − 1 × 5 即 x c 为 首 个 乘 以 5 后 大 于 x n 的 丑 数 \left\{ \begin{array}{lcl} x_a\times2 >x_n\geq x_{a-1} \times2 & & 即x_a为首个乘以2后大于x_n的丑数\\ x_b\times3 >x_n\geq x_{b-1} \times3 & & 即x_b为首个乘以3后大于x_n的丑数\\ x_c\times5 >x_n\geq x_{c-1} \times5 & & 即x_c为首个乘以5后大于x_n的丑数 \end{array} \right. xa×2>xnxa1×2xb×3>xnxb1×3xc×5>xnxc1×5xa2xnxb3xnxc5xn

若索引a,b,c满足以上条件,则可使用递推公式计算下个丑数 x n + 1 x_{n+1} xn+1,其为三种情况中的最小值,即:
x n + 1 = m i n ( x a × 2 , x b × 3 , x c × 5 ) x_{n+1}=min(x_a \times 2,x_b \times 3,x_c \times 5) xn+1=min(xa×2,xb×3,xc×5)
因此,可设置指针a,b,c指向首个丑数(即1),循环根据递推公式得到下个丑数,并每轮将对应指针执行+1即可。

在这里插入图片描述
动态规划解析:

  • 状态定义:设动态规划列表dp,dp[i]代表第i+1个丑数。
  • 转移方程:
    1. 当索引a,b,c满足以下条件时,dp[i]为三种情况的最小值;
    2. 每轮计算dp[i]后,需要更新索引a,b,c的值,使其始终满足方程条件。实现方法:分别独立判断 d p [ i ] dp[i] dp[i] d p [ a ] × 2 dp[a] \times 2 dp[a]×2 d p [ b ] × 3 dp[b] \times 3 dp[b]×3 d p [ c ] × 5 dp[c] \times 5 dp[c]×5的大小关系,若相等则将对应索引a,b,c加1。
      { d p [ a ] × 2 > d p [ i − 1 ] ≥ d p [ a − 1 ] × 2 d p [ b ] × 3 > d p [ i − 1 ] ≥ d p [ b − 1 ] × 3 d p [ c ] × 5 > d p [ i − 1 ] ≥ d p [ c − 1 ] × 5 \left\{ \begin{array}{lcl} dp[a]\times2 >dp[i-1]\geq dp[a-1] \times2 \\ dp[b]\times3 >dp[i-1]\geq dp[b-1] \times3 \\ dp[c]\times5 >dp[i-1]\geq dp[c-1] \times5 \end{array} \right. dp[a]×2>dp[i1]dp[a1]×2dp[b]×3>dp[i1]dp[b1]×3dp[c]×5>dp[i1]dp[c1]×5
      d p [ i ] = m i n ( d p [ a ] × 2 , d p [ b ] × 3 , d p [ c ] × 5 ) dp[i]=min(dp[a]\times2,dp[b]\times3,dp[c]\times5) dp[i]=min(dp[a]×2,dp[b]×3,dp[c]×5)
  • 初始状态:dp[0]=1,即第一个丑数为1;
  • 返回值:dp[n-1],即返回第n个丑数。
class Solution {
    
    
    public int nthUglyNumber(int n) {
    
    
        int a = 0, b = 0, c = 0;
        int[] dp = new int[n];
        dp[0] = 1;
        for (int i = 1;i < n;i++) {
    
    
            int n2 = dp[a] * 2;
            int n3 = dp[b] * 3;
            int n5 = dp[c] * 5;
            dp[i] = Math.min(Math.min(n2,n3),n5);
            if (dp[i] == n2) a++;
            if (dp[i] == n3) b++;
            if (dp[i] == n5) c++;
        }
        return dp[n-1];
    }
}

复杂度分析:

  • 时间复杂度 O(N) : 其中 N=n ,动态规划需遍历计算 dp 列表。
  • 空间复杂度 O(N) : 长度为 N 的 dp 列表使用 O(N) 的额外空间。

猜你喜欢

转载自blog.csdn.net/qq_41242680/article/details/113459505