丑数II

题目描述

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

丑数 就是质因子只包含 23 和 5 的正整数。

示例 1:

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

示例 2:

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

提示:

  • 1 <= n <= 1690

解题思路

class Solution {
public:
    int nthUglyNumber(int n) {
        // 小顶堆+集合去从
        priority_queue<long long, vector<long long>, greater<long long>> pq;
        unordered_set<long long> uniset;
        pq.push(1);
        while (--n) {
            auto u = pq.top();
            pq.pop();
            if (!uniset.count(2 * u)) {
                uniset.insert(2 * u);
                pq.push(2 * u);
            }
            if (!uniset.count(3 * u)) {
                uniset.insert(3 * u);
                pq.push(3 * u);
            }
            if (!uniset.count(5 * u)) {
                uniset.insert(5 * u);
                pq.push(5 * u);
            }
        }
        return pq.top();
    }
};

采用了小顶堆(优先队列)和集合(哈希表)的组合来实现。基本思路是从最小的丑数开始(即 1),通过乘以 2、3、5 来生成新的丑数,并使用优先队列来保持丑数的排序,同时用集合来避免重复计算相同的丑数。

以下是详细的解析:

初始化

  • 使用 priority_queue<long long, vector<long long>, greater<long long>> 来创建一个小顶堆,这里的 greater 是使堆成为最小堆,即堆顶是最小元素。
  • 使用 unordered_set<long long> 来记录已经生成的丑数,防止重复计算。

生成丑数

  • 将 1 作为第一个丑数推入小顶堆和集合中。
  • 进行循环,每次循环找到当前堆顶的丑数(即当前最小的丑数),并将其从堆中弹出。
  • 使用当前丑数生成新的丑数(乘以 2、3、5),并检查新生成的丑数是否已存在于集合中:
    • 如果不存在,将其加入集合和堆中。
  • 循环 n-1 次(因为第一次已经包括了丑数 1),最后堆顶的元素就是第 n 个丑数。

返回结果

  • 在循环结束后,堆顶元素是第 n 个丑数,将其返回。

代码优点

  • 效率:通过小顶堆维护丑数的顺序,可以快速获取下一个最小丑数,保证了算法的效率。
  • 去重:使用哈希集合有效避免了生成重复的丑数,节约了空间和时间。
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

LIHAORAN99

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

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

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

打赏作者

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

抵扣说明:

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

余额充值