前置题目:LeeCode_263. 丑数(对2、3、5整除)
一、介绍
1.题目描述
题目链接:https://leetcode-cn.com/problems/ugly-number-ii/
给你一个整数 n
,请你找出并返回第 n
个 丑数 。
丑数 就是只包含质因数 2
、3
和/或 5
的正整数。
2.测试样例
10 # 12
1 # 1
1690 # 2123366400
二、题解
1、小顶堆🔴
1、我们可以构造一个小顶堆,初始内容为1
2、由于丑数是2、3、5的倍数,对1分别乘上2、3、5加入小顶堆。
3、取小顶堆中的堆顶(即最小数),分别乘上2、3、5加入小顶堆
4、重复以上步骤,直到第 n 次取到堆顶元素后,就代表第 n 个丑数
由于数字有可能重复(例如数字6=2×3),定义 set s 用于看该数字是否和之前重复。
定义 priority_queue 构造小顶堆。
参考链接:https://leetcode-cn.com/problems/ugly-number-ii/solution/chou-shu-ii-by-leetcode-solution-uoqd/
class Solution {
public:
int nthUglyNumber(int n) {
// 判重
unordered_set<long> s;
// 小顶堆
priority_queue<long,vector<long>,greater<long>> heap;
// 倍数
vector<int> x={2,3,5};
// 推入1
s.insert(1);
heap.push(1);
long ans=1;
for(int i=0;i<n;i++){
ans=heap.top();
heap.pop();
// 乘上倍数,若不重复则推入小顶堆
for(int x:x){
long t=ans*x;
if(!s.count(t)){
s.insert(t);
heap.push(t);
}
}
}
return ans;
}
};
2、动态规划🔴
除1外,丑数必定是2的倍数、3的倍数、5的倍数。
因此有三个列表 [1,2,4,6,8,...]、[1,3,6,9,12,...]、[1,5,10,15,...],本质是将该三个数组合并去重。
dp是记录丑数的数组,dp[0]=1。定义指针p2、p3、p5,初始时全部指向1,p2=p3=p5=0。
比较 dp[p2]*2,dp[p3]*3,dp[p5]*5 的最小值,加入到dp中,将最小值所用到的指针 pi 在dp中后移。
- dp [ pi ] * i 的值有多个相等时,多个指针后移
- 后移后的相乘结果必定 > 当前dp中的所有值
class Solution {
public:
int nthUglyNumber(int n) {
int dp[n];
dp[0]=1;
int p2=0,p3=0,p5=0;
for(int i=1;i<n;i++){
int a=dp[p2]*2,b=dp[p3]*3,c=dp[p5]*5;
dp[i]=min(min(a,b),c);
if(dp[i]==a) p2++;
if(dp[i]==b) p3++;
if(dp[i]==c) p5++;
}
return dp[n-1];
}
};