Problem
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.
Example 1:
Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:
Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4
Note:
You may assume k is always valid, 1 ≤ k ≤ array’s length.
解题思路
很显然,这一题的思路是使用堆来求解(能使用堆的地方往往都可以使用排序),因此,我们只需要每次求解出当前堆最大的那个元素,将其除外,重复k次即可。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k)
{
for (size_t i = 0; i < k; ++i)
{
make_heap(nums.begin() + i, nums.end());
}
return nums[k - 1];
}
};
这么提交的结果是时间花费很大(1764 ms),但是并没有超时。
当我们选择进行排序的时候,时间花费反而更小。
class Solution {
public:
int findKthLargest(vector<int>& nums, int k)
{
// for (size_t i = 0; i < k; ++i)
// {
// make_heap(nums.begin() + i, nums.end());
// }
sort(nums.begin(), nums.end(), [](int a, int b){return a > b;});
return nums[k - 1];
}
};
时间花费为12 ms,远小于堆排序。
除了以上的两种常见的思路外,我们还可以借鉴快速排序的思想。由题意可以知道,我们这里选择降序排序。当我们选择第一个数作为分割中点时,我们来考虑这个分割中点的位置,如果正好等于k,则正好是我们需要的数据,返回即可;如果大于k,则说明我们需要的数据位于左侧;如果小于k,则说明我们需要的数据位于右侧。然后再相应的一侧继续查找即可。代码如下:
class Solution {
public:
int findKthLargest(vector<int>& nums, int k)
{
int ans;
qsort(nums, 0, nums.size() - 1, k - 1, ans);
return ans;
}
private:
void qsort(vector<int>& nums, int start, int end, int k, int& ans)
{
if (start > end)
{
return;
}
int key = nums[start];
int left = start;
int right = end;
while (left < right)
{
while (left < right && nums[right] < key)
{
right--;
}
if (left < right)
{
nums[left] = nums[right];
left++;
}
while (left < right && nums[left] > key)
{
left++;
}
if (left < right)
{
nums[right] = nums[left];
right--;
}
}
nums[left] = key;
if (left == k)
{
ans = nums[k];
return;
}
if (left < k)
{
qsort(nums, left + 1, end, k, ans);
}
else
{
qsort(nums, start, left - 1, k, ans);
}
}
};