力扣hot100——堆

215. 数组中的第K个最大元素

快速排序

cpp 复制代码
class Solution {
public:
    int findKthLargest(vector<int>& a, int k) {
        auto qsort = [&](this auto&& qsort, int l, int r) -> void {
            if (l == r) return;
            int i = l - 1, j = r + 1;
            int x = a[(l + r) / 2];

            /*
                如果把>改成>=,<改成<=,相同的数不就不交换,不就变成稳定的排序了?
                实际上坚决不可以这样做,因为一旦x是整个数列里最大的数,i向右移动,是找不到大于x的数的,就会越界,
                除非增加很多判断语句,要么限制x的越界,要么特判相等时不交换
            */
            while (i < j) {
                do {
                    i++;
                } while (a[i] < x);
                do {
                    j--;
                } while (a[j] > x);
                if (i < j) swap(a[i], a[j]);
            }
            /*
                注意这里边界是j,和二分法一样记住就行了,特别的细节
            */
            qsort(l, j);
            qsort(j + 1, r);
            };
        qsort(0, (int)a.size() - 1);
        return a[a.size() - k];
    }
};

线性时间选择

cpp 复制代码
class Solution {
public:
    int findKthLargest(vector<int>& a, int k) {
        auto qsort = [&](this auto&& qsort, int l, int r, int k) -> int {
            if (l == r) return a[k];
            int i = l - 1, j = r + 1;
            int x = a[(l + r) / 2];
            while (i < j) {
                do {
                    i++;
                } while (a[i] < x);
                do {
                    j--;
                } while (a[j] > x);
                if (i < j) swap(a[i], a[j]);
            }
            if (k <= j) return qsort(l, j, k);
            else return qsort(j + 1, r, k);
            };
        
        return qsort(0, (int)a.size() - 1, (int)a.size() - k);
    }
};

平均复杂度O(n):

在分解的过程当中,我们会对子数组进行划分,如果划分得到的 q 正好就是我们需要的下标,就直接返回 a[q];否则,如果 q 比目标下标小,就递归右子区间,否则递归左子区间。这样就可以把原来递归两个区间变成只递归一个区间,提高了时间效率。这就是「快速选择」算法。

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

需要注意的是,这个时间复杂度只有在 随机数据 下才成立,而对于精心构造的数据则可能表现不佳。因此我们这里并没有真正地使用随机数,而是使用双指针的方法,这种方法能够较好地应对各种数据。

347. 前 K 个高频元素

cpp 复制代码
class Solution {
public:
    vector<int> topKFrequent(vector<int>& a, int k) {
        map<int, int> mp;
        for (auto x : a) mp[x]++;
        vector<pair<int, int>> v;
        vector<int> ans;
        for (auto [x, y] : mp) {
            v.push_back({ y, x });
        }
        sort(v.begin(), v.end(), greater<>());
        for (int i = 0; i < k; i++) {
            ans.push_back(v[i].second);
        }
        return ans;
    }
};

295. 数据流的中位数

cpp 复制代码
class MedianFinder {
public:
    priority_queue<int, vector<int>, less<int>> q1; //大根堆
    priority_queue<int, vector<int>, greater<int>> q2;
    int sz;
    MedianFinder() {
        sz = 0;
    }

    void addNum(int x) {
        if (q2.empty() || x >= q2.top()) q2.push(x);
        else q1.push(x);
        sz++;
        while (q2.size() > (sz + 1) / 2) q1.push(q2.top()), q2.pop();
        while (q2.size() < (sz + 1) / 2) q2.push(q1.top()), q1.pop();
    }

    double findMedian() {
        if (sz & 1) return q2.top();
        else return (q1.top() + q2.top() + 0.0) / 2;
    }
};

对顶堆板子题,这是动态求第k大的模板(k可变化)

相关推荐
槐月杰4 小时前
C语言中冒泡排序和快速排序的区别
c语言·算法·排序算法
笺上山河梦6 小时前
文件操作(二进制文件)
开发语言·c++·学习·算法
大慕慕好懒6 小时前
PHP弱类型hash比较缺陷
算法·哈希算法
snowfoootball7 小时前
最短路问题
数据结构·算法
有你的冬天1988 小时前
数据结构(一)
数据结构·算法
满怀10158 小时前
【Python进阶】列表:全面解析与实战指南
python·算法
爱学习的uu8 小时前
决策树:ID3,C4.5,CART树总结
算法·决策树·机器学习
wuqingshun3141599 小时前
蓝桥杯 9. 九宫幻方
数据结构·c++·算法·职场和发展·蓝桥杯·深度优先
小技与小术9 小时前
代码随想录算法训练营day4(链表)
数据结构·python·算法·链表
yasuniko9 小时前
C复习(主要复习)
c语言·数据结构·算法