第二周 leetcode 215. Kth Largest Element in an Array(Medium)
题目描述:
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4] and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.
解题思路:
- 这个题我们可以轻松的想到一种常规的解法,就是先将数组降序排序,然后通过检索数组下标就能查找到第k大的元素。这种解法我们需要完成数组排序和线性查找两个步骤,算法的时间复杂度明显比较大。
- 从快排算法的灵感,这种题我们可以采用分而治之的思想,通过将原数组不断进行划分,减小目标的查找范围,从而减小算法的时间复杂度。
- 主要具体思路是,利用快排的partition函数思想,选定一个数组内的值作为pivot,将小于pivot的数字放到pivot右边,大于等于pivot的数字放到pivot左边。接着判断两边数字的数量,如果左边的数量小于k个,说明第k大的数字存在于pivot及pivot右边的区域之内,对右半区执行partition函数;如果右边的数量小于k个,说明第k大的数字在pivot和pivot左边的区域之内,对左半区执行partition函数。直到左半区刚好有k-1个数,那么第k大的数就已经找到了。
代码:
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
int high = nums.size();
int low = 0;
while (low < high) {
int i = low;
int j = high-1;
int pivot = nums[low];
// 从low到high对数组划界
while (i <= j) {
while (i <= j && nums[i] >= pivot) // 比划界元大的保留在前面
i++;
while (i <= j && nums[j] < pivot) // 比划界元小的保留在后面
j--;
if (i < j) // 否则交换元素后,循环执行上述步骤,直至i > j
swap(nums[i++],nums[j--]);
}
swap(nums[low],nums[j]); // 把划界元交换至划界处
if (j == k-1) // nums[j]恰好为第k大元素
return nums[j];
else if (j < k-1) // 第k大元素在数组右半区
low = j+1;
else // 第k大元素在数组左半区
high = j;
}
}
};
代码运行结果: