https://leetcode-cn.com/problems/get-kth-magic-number-lcci/
思路一:为了满足题意,对于 v a l val val,我们有三种扩展方式: 3 ∗ v a l 、 5 ∗ v a l 、 7 ∗ v a l 3*val、5*val、7*val 3∗val、5∗val、7∗val。那么自然想到用优先队列存储数据,每次取出最小的进行扩展,那么第 k k k次出队的数就是答案。为了去重,我们还需要一个 m a p map map,为了防止计算过程溢出 i n t int int,我们需要用 l o n g l o n g long long longlong。
class Solution {
public:
using ll=long long;
int getKthMagicNumber(int k) {
priority_queue<ll,vector<ll>,greater<ll>> q;
map<ll,bool> m;
q.push(1);
--k;
while(k){
ll val=q.top();
q.pop();
--k;
if(m[val*3]==0)
m[val*3]=1,q.push(val*3);
if(m[val*5]==0)
m[val*5]=1,q.push(val*5);
if(m[val*7]==0)
m[val*7]=1,q.push(val*7);
}
return q.top();
}
};
思路二:在思路一的基础上进行优化,通过 s e t set set即可实现全部需求。
class Solution {
public:
using ll=long long;
int getKthMagicNumber(int k) {
set<ll> s;
--k;
s.insert(1);
while(k){
ll val=*s.begin();
--k;
s.erase(s.begin());
s.insert(val*3);
s.insert(val*5);
s.insert(val*7);
}
return *s.begin();
}
};
思路三:我们不妨假设这个序列为 v e c vec vec, v e c [ 0 ] = 1 , v e c [ 1 ] = 3 , … … vec[0]=1,vec[1]=3,…… vec[0]=1,vec[1]=3,……单独考虑 3 、 5 、 7 3、5、7 3、5、7,其实可以把它拆分成三个序列出来: ( 1 ) v e c [ i ] ∗ 3 , i > = 0 (1)vec[i]*3,i>=0 (1)vec[i]∗3,i>=0; ( 2 ) v e c [ i ] ∗ 5 , i > = 0 (2)vec[i]*5,i>=0 (2)vec[i]∗5,i>=0; ( 3 ) v e c [ i ] ∗ 7 , i > = 0 (3)vec[i]*7,i>=0 (3)vec[i]∗7,i>=0。每个序列都是单调递增的,而 v e c vec vec就是把上述三个序列合并去重后的结果。合并三个有序序列……完全可以在线性复杂度内完成。具体看代码。
class Solution {
public:
using ll=long long;
int getKthMagicNumber(int k) {
//序列
vector<int> vec(k);
//三个系数 3 5 7
//pos存放当前每个系数对应的位置
int tmp[3],xs[3]={3,5,7},pos[3]={0,0,0};
vec[0]=1;
for(int i=1;i<k;i++){
//分别计算出来这三个数
for(int j=0;j<3;j++)
tmp[j]=vec[pos[j]]*xs[j];
//取最小值
int MIN=min({tmp[0],tmp[1],tmp[2]});
vec[i]=MIN;
for(int j=0;j<3;j++){
//关键操作--通过一次遍历 去掉重复元素
if(MIN==tmp[j])
++pos[j];
}
}
return vec[k-1];
}
};