在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和
k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和
k = 4
输出: 4
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
思路:这里采用了快速排序中的子函数partion,这个函数的作用是每次以基准数字为标准进行排序,最后的结果是返回基准数字的下标并保证下标以左的数字都比基准数字大,下标以右的数字都比基准数字小,这样函数partition返回的下标就可以用来类似二分法来对不同区间进行搜索。
1:如果返回下标index==(k-1),则index下标对应的数值就是第k个大的元素,直接返回nums[index]
2:如果返回下标index>(k-1),则index下标对应的数值比第k个元素大,我们应该在前半段数组中搜索,递归调用原函数,搜索区间限制为[left,index-1]
3:如果返回下标index<(k-1),则index下标对应的数值比第k个元素小,我们应该在后半段数组中搜索,递归调用原函数,搜索区间限制为[index+1,right]
参考代码如下:
int partition(vector<int>& nums, int left, int right, int k) {
if(left>=right){
return left;
}
int cur = nums[left];
int i_left = left;
int i_right = right;
while (i_left < i_right) {
while (nums[i_right] <= cur && i_left < i_right) {
i_right--;
}
while (nums[i_left] >= cur && i_left < i_right) {
i_left++;
}
if (i_left< i_right) {
int tmp = nums[i_left];
nums[i_left] = nums[i_right];
nums[i_right] = tmp;
}
}
nums[left] = nums[i_left];
nums[i_left] = cur;
return i_left;
}
int findKthLargestCore(vector<int>& nums, int k, int left, int right) {
int index = partition(nums, left, right, k);
if (index == (k-1)) {
return nums[index];
}
else if (index > (k-1)) {
return findKthLargestCore(nums,k,left,index-1);
}
else {
return findKthLargestCore(nums, k, index+1, right);
}
}
int findKthLargest(vector<int>& nums, int k) {
return findKthLargestCore(nums, k, 0, nums.size() - 1);
}