mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
4.2 KiB
4.2 KiB
215. Kth Largest Element in an Array
思路
给定一个数组, 要求返回其中第k大的数. 这应该属于常考的面试题了, 务必掌握. 有两个基本的思路: 快排划分的思想和最大(小)堆.
时间复杂度平均为O(n)
思路一
我们回忆一下快排中的partition函数: 每次先(任意)确定一个中枢值pivot,然后遍历其他所有的数字,像这道题从大往小排的话,就把大于中枢点的数字放到左半边, 把小于中枢点的放在右半边,这样中枢点是整个数组中第几大的数字就确定了,虽然左右两部分各自不一定是完全有序的.
所以我们只需要调用partition函数,
- 若得到pivot的最终位置pos刚好就是k-1, 那直接返回nums[k-1];
- 若得到的pos比k-1小, 那在pos右边继续调用partition;
- 否则, 在pos左边继续调用partition.
其实STL中nth_element
已经帮我们实现了上述过程, 注意学习使用.
nth_element
只保证第n(从0开始)个元素是位于最终排序位置的, 但其左右两边的元素则不一定有序.
思路二
用最小堆, 最小堆(实际不是堆是个二叉树)始终保持最小元素在树顶, 那么我们不断去掉top元素知道只剩下k个元素, 那剩下的top元素即所求.
或者用最大堆, 这样我们不断去掉k-1个最大堆树顶元素后第k大的元素就位于树顶了.
在STL中, priority_queue
和multiset
都可用来作为最小(大)堆, 代码以前者为例, 用multiset
可以参考此处
注意用priority_queue如何实现最大(小)堆, 即如何自定义比较方法(和sort、nth_element、partial_sort函数自定义比较函数写法不一样)
其实, STL里有一个函数可以实现部分排序即partial_sort
, 给定位置k, 该函数会将位置k前(不包含k)的元素排好序, 而k及之后元素则不一定有序.
建议详读讨论区总结
C++
思路一
class Solution {
private:
int partition(vector<int> &nums, int low, int high){
int i = low, j = high;
int pivot = nums[low];
while(i < j){
while(i < j && nums[j] < pivot) j--;
nums[i] = nums[j]; // 将比pivot大的元素移到pivot左边
while(i < j && nums[i] >= pivot) i++;
nums[j] = nums[i]; // 将比pivot小的元素移到pivot右边
}
nums[i] = pivot;
return i;
}
public:
int findKthLargest(vector<int>& nums, int k){
int low = 0, high = nums.size() - 1, pos;
while(true){
pos = partition(nums, low, high);
if(pos == k - 1) return nums[pos];
if(pos < k - 1) low = pos + 1;
else high = pos - 1;
}
}
};
思路一STL版
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
// greater和less都重载了操作符()
nth_element(nums.begin(), nums.begin() + k - 1, nums.end(), greater<int>());
return nums[k - 1];
}
};
思路二
class Solution {
static bool comp_func(const int &a, const int &b){
return a > b;
}
struct comp_class{
bool operator()(const int &a, const int &b){
return a > b;
}
};
public:
int findKthLargest(vector<int>& nums, int k){
// 以下三种写法都是可以的. 默认为最大堆: priority_queue<int, vector<int> > pq;
// priority_queue<int, vector<int>, greater<int>> pq;
// priority_queue<int, vector<int>, bool (*)(const int &a, const int &b) > pq(comp_func);
priority_queue<int, vector<int>, comp_class > pq;
for (int num : nums) {
pq.push(num);
if (pq.size() > k) {
pq.pop();
}
}
return pq.top();
}
};
思路二STL版
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
partial_sort(nums.begin(), nums.begin() + k, nums.end(), greater<int>());
return nums[k - 1];
}
};