LeetCode-动态规划

目录

  • 264. 丑数 II
  • 313.超级丑数

264. 丑数 II

编写一个程序,找出第 n 个丑数。丑数就是质因数只包含 2, 3, 5 的正整数。
在这里插入图片描述
思路
1个丑数也只能是从2,3,5中衍生出来

动态规划: 一个数字可以拆分成若干因子之积,那么我们也可以使用不同因子去构造这个数
定义三个指针 p2、p3、p5 分别乘以 2、3、5 的数字
dp[i] 表示第 i 个丑数。那么 dp[p2] * 2、dp[p3] * 3 和 dp[p5] * 5 中的最小值就是下一个丑数。

小顶堆:
将计算后的全部加入到小顶堆中,注意排重,堆顶就是ans

//动态规划
//一个数的因数也可以构造这个数
int nthUglyNumber(int n) {
    vector<int> dp(n, 0);
    dp[0] = 1;
    //p2表示乘2的指针, p3表示乘3
    int p2 = 0, p3 = 0, p5 = 0;
    for(int i = 1; i < n; i ++){
        //计算当前指针乘相应的数后 取出最小那个,即为构造出的数
        dp[i] = min(min(dp[p2]*2, dp[p3]*3), dp[p5]*5);
        if(dp[i] == dp[p2]*2) p2++;
        if(dp[i] == dp[p3]*3) p3++;
        if(dp[i] == dp[p5]*5) p5++;
    }
    return dp[n - 1];
}

//小顶堆
int nthUglyNumber(int n) {
    priority_queue<long long, vector<long long>, greater<long>> dq;
    set<long long> set;
    dq.push(1);
    set.insert(1);
    vector<int> vt = {2,3,5};
    int ans = 1;
    for (int i = 1; i < n; i++) {
        auto top = dq.top(); dq.pop();
        for (auto t : vt) {
            if (set.find(top * t) == set.end()) {
                dq.push(top * t);
                set.insert(top * t);
            }
        }
        ans = dq.top();
    }
    return ans;
}

313.超级丑数

编写一段程序来查找第 n 个超级丑数。超级丑数是指其所有质因数都是长度为 k 的质数列表 primes 中的正整数。
LeetCode-动态规划_第1张图片
思路
丑数问题都可以用小顶堆解决,当然是效率最慢的解决方法

小顶堆
将计算后的值放入队列中,第n次弹出的数就是答案

动态规划
实际就是把之前的3数换成了数组而已, 原理一样,每个primes数都对应indexs数组中记录着指向dp的index

//小顶堆
int nthSuperUglyNumber(int n, vector<int> &primes) {
    priority_queue<long long , vector<long long>, greater<long long>> min_buf;
    unordered_set<long long> set;
    min_buf.push(1);
    set.insert(1);
    long long ans = 1;
    for (int i = 0; i < n; i++) {
       // 当i是1的时候弹出的就是第一个丑数
        ans = min_buf.top(); min_buf.pop();
        for (auto p : primes) {
            long long num = (long long)ans * p;
            //题目不可大于32位
            if (num <=INT32_MAX && set.find(num) == set.end()) {
                min_buf.push(num);
                set.insert(num);
            }
        }
    }
    return ans;
}

//动态规划
int nthSuperUglyNumber(int n, vector<int>& primes) {
        int len = primes.size();
        vector<int> dp(n,1);
        //记录每个指针指向dp的index
        vector<int> index(len,0);
        for(int i = 1; i < n; i++){
            int minNum = INT_MAX;
            //找出最小
            for(int j = 0; j < len; j++) {
                minNum = min(minNum, dp[index[j]]*primes[j]);     
            }
            //找到能够相乘为minNum的指针都+1   
            for(int j = 0; j < len; j++) {
                if(dp[index[j]]*primes[j] == minNum) {
                  index[j]++;
                }  
            }
               
            dp[i] = minNum;
        }
        return dp[n-1];
    }
``

你可能感兴趣的:(LeetCode刷题)