# 题目

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

输入:[3,2,3,1,2,4,5,5,6] 和 k = 4
输出:4

# 暴力求解

#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
    int findKthLargest(vector<int> &nums, int k) {
        int size = nums.size();
        sort(begin(nums), end(nums));
        return nums[size - k];
    }
};

# 大顶堆

调用 priority_queue

class Solution
{
public:
    int findKthLargest(vector<int> &nums, int k)
    {
        priority_queue<int, vector<int>, less<int>> maxHeap;
        for (int x : nums)
            maxHeap.push(x);
        for (int _ = 0; _ < k - 1; _++)
            maxHeap.pop();
        return maxHeap.top();
    }
};

NB solution

class Solution
{
public:
    void shiftDown(vector<int> &nums, int i, int len)
    {
        int root = i;
        while (root < len)
        {
            int tmp = root;
            int left = 2 * root + 1, right = 2 * root + 2;
            if (left < len && nums[root] < nums[left])
            {
                root = left;
            }
            if (right < len && nums[root] < nums[right])
            {
                root = right;
            }
            if (root == tmp)
            {
                break;
            }
            swap(nums[tmp], nums[root]);
        }
    }
    void buildHeap(vector<int> &nums)
    {
        int n = nums.size();
        for (int i = n / 2 - 1; i >= 0; i--)
        {
            shiftDown(nums, i, n);
        }
    }
    int findKthLargest(vector<int> &nums, int k)
    {
        // 构建最大堆
        buildHeap(nums);
        int n = nums.size();
        //pop k-1 个元素
        for (int i = n - 1; i > n - k; i--)
        {
            swap(nums[0], nums[i]);
            shiftDown(nums, 0, i);
        }
        return nums[0];
    }
};

# 优先队列

其内部可以看作是一棵由数组模拟的完全二叉树,对于这棵树的每一个结点来说,自身的优先级不低于左右孩子的优先级,所以其功能就是拿出优先级最大的元素,如何简单使用 C++ 中内置容器 priority_queue ?首先引出头文件 <queue> ,定义一个默认的优先队列(大顶堆) priority_queue<int> que; 即值越大的元素优先级越高先出队。

  • que.size () 元素数量
  • que.push (x) 插入 x
  • que.pop () 删除优先级最高的元素
  • que.top () 访问优先级最高的元素(堆顶元素)
  • que.empty () 判空

对于优先队列的操作,插入删除的时间复杂度为对数级,访问堆顶元素时间复杂度为常数级,所以比较适合动态调整,获得极值。

#include <iostream>
#include <queue>
using namespace std;
// 大顶堆
int main()
{
    priority_queue<int> que;
    que.push(7);
    que.push(5);
    que.push(-2);
    que.push(1);
    que.push(6);
    cout << que.size() << endl;
    while (!que.empty())
    {
        cout << que.top() << " ";
        que.pop();
    }
    cout << endl;
    return 0;
}

如何定义一个小顶堆?优先队列除了第一个数据类型以外,还有其他两个模板参数:底层顺序结构类型(默认是 vector,也可使用 queue 或者 array),第三个参数是一个仿函数,提供优先队列权值比较方法。

priority_queue<int, vector<int>, less<int>> q;    // 大顶堆
priority_queue<int, vector<int>, greater<int>> q; // 小顶堆

其中 greater<int>less<int> 即为仿函数,其中 greater 的实现如下

template <class T>
struct greater : public binary_function<T, T, bool>
{
    bool operator()(const T &x, const T &y) const
    {
        return x > y;
    }
}
#include <iostream>
#include <queue>
using namespace std;
// 小顶堆
int main()
{
    priority_queue<int, vector<int>, greater<int>> que;
    que.push(7);
    que.push(5);
    que.push(-2);
    que.push(1);
    que.push(6);
    cout << que.size() << endl;
    while (!que.empty())
    {
        cout << que.top() << " ";
        que.pop();
    }
    cout << endl;
    return 0;
}

定义一个自定义类型的优先队列

#include <iostream>
#include <queue>
using namespace std;
struct node
{
    int x, y;
    // 重载运算符,重载小于号,若需小根堆,this->x > b.x 即可
    bool operator<(const node &b) const
    {
        return this->x < b.x;
    }
};
int main()
{
    priority_queue<node> que;
    que.push((node){1, 5});
    que.push((node){2, 3});
    que.push((node){9, 4});
    que.push((node){-5, 5});
    while (!que.empty())
    {
        cout << que.top().x << endl;
        que.pop();
    }
    return 0;
}
[root@VM-12-16-centos lab]# ./a.out 
9
2
1
-5