49. 丑数

本文介绍了如何使用动态规划和小根堆算法解决LeetCode中的剑指Offer问题49——找到第n+1个丑数。通过理解丑数的定义和递推性质,利用三个指针分别跟踪乘以2、3和5的最小丑数,实现了O(n)和O(n*logn)两种时间复杂度的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指 Offer 49. 丑数

思路:动态规划

设已知长度为n的丑数序列 x 1 , x 2 , x 3 , ⋯   , x n x_1,x_2,x_3,\cdots,x_n x1,x2,x3,,xn,求第n+1个丑数,根据递推性质,丑数 x n + 1 x_{n+1} xn+1只可能为:
f ( x ) = { x a × 2 a ∈ [ 1 , n ] x b × 3 b ∈ [ 1 , n ] x c × 5 c ∈ [ 1 , n ] f(x)=\begin{cases} x_a\times2 & {a\in[1,n]}\\ x_b\times3 & {b\in[1,n]}\\ x_c\times5 & {c\in[1,n]} \end{cases} f(x)=xa×2xb×3xc×5a[1,n]b[1,n]c[1,n]
丑数递推公式为:

x n + 1 = m i n ( x a × 2 , x b × 3 , x c × 5 ) x_{n+1}=min(x_a\times2,x_b\times3,x_c\times5) xn+1=min(xa×2,xb×3,xc×5)

由于 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 的 丑 数 \begin{cases} x_a\times2>x_n\ge x_{a-1}\times2 &即x_a为首个乘以2后大于x_n的丑数\\ x_b\times3>x_n\ge x_{b-1}\times3 &即x_b为首个乘以3后大于x_n的丑数\\ x_c\times5>x_n\ge x_{c-1}\times5 &即x_c为首个乘以5后大于x_n的丑数 \end{cases} xa×2>xnxa1×2xb×3>xnxb1×3xc×5>xnxc1×5xa2xnxb3xnxc5xn
因此,设置指针a,b,c指向首个丑数,循环递推公式得到下个丑数,并每轮将对应指针+1

class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int> dp(n);
        dp[0]=1;
        int a=0,b=0,c=0;
        for(int i=1;i<n;++i){
            int na=dp[a]*2;
            int nb=dp[b]*3;
            int nc=dp[c]*5;
            dp[i]=min(na,min(nb,nc));
            if(dp[i]==na)++a;
            if(dp[i]==nb)++b;
            if(dp[i]==nc)++c;
        }
        return dp[n-1];
    }
};

时间复杂度 O(n)

空间复杂度 O(n)

思路:小根堆+哈希表去重

class Solution {
public:
    int nthUglyNumber(int n) {
        vector<int> factors={2,3,5};
        unordered_set<long> seen;
        priority_queue<long,vector<long>,greater<long>> heap;
        seen.insert(1L);
        heap.push(1L);
        int ugly=0;
        for(int i=0;i<n;++i){
            long curr=heap.top();
            heap.pop();
            ugly=int(curr);
            for(int factor:factors){
                long next=curr*factor;
                if(!seen.count(next)){
                    seen.insert(next);
                    heap.push(next);
                }
            }
        }
        return ugly;
    }
};

时间复杂度 O(n*logn)

空间复杂度 O(n)

数字游戏 鼠[冲 马] 06,18,30,42 牛[冲 羊] 05,17,29,41 虎[冲 猴] 04,16,28,40 兔[冲 鸡] 03,15,27,39 龙[冲 狗] 02,14,26,38 蛇[冲 猪] 01,13,25,37,49 马[冲 鼠] 12,24,36,48 羊[冲 牛] 11,23,35,47 猴[冲 虎] 10,22,34,46 鸡[冲 兔] 09,21,33,45 狗[冲 龙] 08,20,32,44 猪[冲 蛇] 07,19,31,43 五行对照,金木水火土的顺序, 金 03,04,11,12,25,26,33,34,41,42 木 07,08,15,16,23,24,37,38,45,46 水 13,14,21,22,29,30,43,44 火 01,02,09,10,17,18,31,32,39,40,47,48 土 05,06,19,20,27,28,35,36,49 波色 红波 01,02,07,08,12,13,18,19,23,24,29,30,34,35,40,45,46 蓝波 03,04,09,10,14,15,20,25,26,31,36,37,41,42,47,48 绿波 05,06,11,16,17,21,22,27,28,32,33,38,39,43,44,49 合数单双 合数单 01,03,05,07,09,10,12,14,16,18,21,23,25,27,29,30,32,34,36,38,41,43,45,47,49 合数双 02,04,06,08,11,13,15,17,19,20,22,24,26,28,31,33,35,37,39,40,42,44,46,48 生肖属性 家禽:牛、马、羊、鸡、狗、猪 野兽:鼠、虎、兔、龙、蛇、猴 吉美:兔、龙、蛇、马、羊、鸡 凶丑:鼠、牛、虎、猴、狗、猪 阴性:鼠、龙、蛇、马、狗、猪 阳性:牛、虎、兔、羊、猴、鸡 单笔:鼠、龙、马、蛇、鸡、猪 双笔:虎、猴、狗、兔、羊、牛 天肖:兔、马、猴、猪、牛、龙 地肖:蛇、羊、鸡、狗、鼠、虎 白边:鼠、牛、虎、鸡、狗、猪 黑中:兔、龙、蛇、马、羊、猴 女肖:兔、蛇、羊、鸡、猪 男肖:鼠、牛、虎、龙、马、猴、狗 三合:鼠龙猴、牛蛇鸡、虎马狗、兔羊猪 六合:鼠牛、龙鸡、虎猪、蛇猴、兔狗、马羊 新六合:鼠马,牛羊,虎猴,兔鸡,龙狗,蛇猪 琴:兔蛇鸡 棋:鼠牛狗 书:虎龙马 画:羊猴猪 五福肖:鼠、虎、兔、蛇、猴 红肖:马、兔、鼠、鸡 蓝肖:蛇、虎、猪、猴 绿肖:羊、龙、牛、狗 按照以上数字,和生肖 分别是 第一个13蛇水 第二个25蛇金 第三个22猴水 第四个39兔火 第五个48马火 第六个23羊木 第七个21鸡水 第八个29牛水 第九个25蛇金 第十个20狗土 第十一个40虎火 第十二个20狗土 第十三个28虎土 第十四个42鼠金 第十五个37蛇木 第十六个07猪木 第十七个30鼠水 第十八个12马金 第十九个12马金 第二十个18鼠火 第二十一个43猪水 第二十二个05牛土 第二十三个49蛇土 第二十四个10猴火 第二十五个11羊金 第二十六个25蛇金 第二十七个44狗水 第二十八个42鼠金 第二十九个20狗土 第三十个31猪火 第三十一个24马木 第三十二个11羊金 第三十三个10猴火 第三十四个35羊土 第三十五个23羊木 第三十六个31猪火 第三十七个48马火 第三十八个12马金 第三十九个44狗水 第十四个44狗水 第四十一个29牛水 第四十二个43猪水 第四十三个49蛇土 第四十四个40虎火 第四十五个03兔金 第四十六个35羊土 第四十七个09鸡火 第四十八个22猴水 根据第一到第四十八的规律,第四十九个是什么?要三个数字是什么?要五个数字是什么?要七个数字是什么?要九个数字是什么?要十一个数字是什么?要十三个数字是什么?一共七个请分别回答。
最新发布
03-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值