215.数组中的第K个最大元素
原题链接
分治方式
这个题目就是快速排序的一个变种(当然直接排序然后输出也是可以的),但是这里使用的是快速选择排序,在快速排序的过程之中可以把答案给找出来。
首先从快排的过程是:先选择一个基准值x,然后根据x将数组二分为了>=x和<=x的两个区间(这里是按降序的规则)然后再进行递归处理。
根据上述的思路,我们知道会有两个区间的产生,但是答案只会存在于其中的一个区间中,只要选择答案存在的哪一个区间就行,另外的一个区间不需要处理
现在就是如何确定我们需要的答案在划分的区间中的哪一个的问题了?只需要将>=x的区间的长度和k进行比较,就能知道答案存在于哪一个区间中了,递归是只选用这个区间就可以了,当递归过程中区间的长度为1的时候,那么那个值就是我们要的答案,因为每次都保证了答案在选择的区间之中
代码如下
class Solution {
public int findKthLargest(int[] nums, int k) {
return quickSort(nums, 0, nums.length - 1, k);
}
public int quickSort(int[] nums, int l, int r, int k){
if(l >= r) return nums[l];
int i = l - 1, j = r + 1, x = nums[l + r >> 1];
while(i < j){
do ++i; while(nums[i] > x);
do --j; while(nums[j] < x);
if(i < j) swap(nums, i, j);
}
if(j - l + 1 >= k) return quickSort(nums, l, j, k);
else return quickSort(nums, j + 1, r, k - (j - l + 1));
}
public void swap(int[] nums, int i, int j){
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
}
上述的方式用的是分治算法
堆的方式
可以直接使用C++中的priority_queue,直接写就行了,大根堆建立完成之后,进行k - 1次删除之后,此时的堆顶元素就是答案
代码如下
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> q;
for(int i = 0; i < nums.size(); ++i) q.push(nums[i]);
while(--k) q.pop();
return q.top();
}
};
下面采用手动建大根堆的方式来写
代码如下
class Solution {
public:
int res[10010];
int findKthLargest(vector<int>& nums, int k) {
int len = nums.size();
for(int i = 0; i < len; ++i) res[i + 1] = nums[i];
for(int i = len / 2; i >= 1; --i) down(i, len);//只需要down一半就行了
while(--k){
res[1] = res[len--];
down(1, len);
}
return res[1];
}
void down(int u, int cnt){
int t = u;
if(u * 2 <= cnt && res[u * 2] > res[t]) t = u * 2;
if(u * 2 + 1 <= cnt && res[u * 2 + 1] > res[t]) t = u * 2 + 1;
if(u != t){//u != t代表了这个值需要down下来
swap(res[u], res[t]);
down(t, cnt);
}
}
};
如有错误,欢迎指正!