力扣 面试题 17.09. 第 k 个数 队列/set

54 篇文章 0 订阅
11 篇文章 0 订阅

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 3val5val7val。那么自然想到用优先队列存储数据,每次取出最小的进行扩展,那么第 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 357,其实可以把它拆分成三个序列出来: ( 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];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值