[M思维] lc313. 超级丑数(多路归并+STL堆)

Posted Ypuyu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[M思维] lc313. 超级丑数(多路归并+STL堆)相关的知识,希望对你有一定的参考价值。

1. 题目来源

链接:313. 超级丑数

前置知识:[M思维] lc264. 丑数 II(多路归并+STL堆)

2. 题目解析

是一道非常经典题目的升级版,[M思维] lc264. 丑数 II(多路归并+STL堆)。但换汤不换药,也依旧采用多路归并的思想,但显然没发用指针来维护,那就用堆来维护就可以了。

方法一:STL堆+多路归并

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        typedef pair<int, int> PII;
        priority_queue<PII, vector<PII>, greater<PII>> heap;
        for (int x: primes) heap.push({x, 0});		// 指针*对应质数,指针的下标
        vector<int> q(n);							// 存储超级丑数
        q[0] = 1;									// 将1放入超级丑数,下标为0
        for (int i = 1; i < n;) {
            auto t = heap.top(); heap.pop();		// 找到最小的超级丑数
            if (t.first != q[i - 1]) q[i ++ ] = t.first;	// 如果不和前一个值相同,即不重复,则为新的超级丑数
            // 指针移动,得到对应的质数p,超级丑数指针下标idx,指针向后走一位。即
            int idx = t.second, p = t.first / q[idx];	
            heap.push({p * q[idx + 1], idx + 1});	// 指针向后移动一位,乘以对应的质数
        }
        return q[n - 1];
    }
};

方法二:STL堆+通用方法

class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        typedef long long LL;
        unordered_set<LL> S;
        priority_queue<LL, vector<LL>, greater<LL>> Q;
        Q.push(1); S.insert(1);

        LL res = 0;
        for (int i = 0; i < n; i ++ ) {
            LL cur = Q.top(); Q.pop();
            res = cur;
            for (int j = 0; j < primes.size(); j ++ ) {
                LL t = cur * primes[j];
                if (!S.count(t)) {
                    S.insert(t);
                    Q.push(t);
                }
            }
        }

        return res;
    }
};

以上是关于[M思维] lc313. 超级丑数(多路归并+STL堆)的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 313. 超级丑数(最小堆动态规划)/413. 等差数列划分/167. 两数之和 II - 输入有序数组

LeetCode 313 超级丑数[动态规划] HERODING的LeetCode之路

微软面试题解析:丑数系列算法

堆的运用——有序元素的多路归并topk问题

算法:多路归并的外排序

leetcode刷题目录