假定pivot选择5,快速选择第二大的数
选择前 | 3 | 1 | 2 | 5 | 6 | 4 |
---|---|---|---|---|---|---|
选择后 | 3 | 1 | 2 | 4 | 6 | 5 |
≤ | 3 | 1 | 2 | 5 | 4 | 6 |
本题题目为Leetcode215. 数组中的第K个最大元素
给定整数数组
nums
和整数k
,请返回数组中第k
个最大的元素。请注意,你需要找的是数组排序后的第
k
个最大的元素,而不是第k
个不同的元素。你必须设计并实现时间复杂度为
O(n)
的算法解决此问题。示例 1:
输入:[3,2,1,5,6,4], k = 2 输出: 5
示例 2:
输入:[3,2,3,1,2,4,5,5,6],k = 4 输出: 4
提示:
1 <= k <= nums.length <= 105
104 <= nums[i] <= 104
class Solution {
public:
void quickselect(vector<int>& nums, int k, int l, int r)
{
int i = l - 1, j = r + 1, pivot = nums[l + r >> 1];
while (i < j){
do i++; while(nums[i] < pivot);
do j--; while(nums[j] > pivot);
if(i < j)swap(nums[i], nums[j]);
}
int sl = j - l + 1;
if(sl == k) return;
if(sl > k) quickselect(nums, k, l, j);
if(sl < k) quickselect(nums, k-sl, j+1, r);
}
int findKthLargest(vector<int>& nums, int k) {
quickselect(nums, nums.size() - k + 1, 0, nums.size() - 1);
return nums[nums.size() - k];
}
};
另外尝试版本,能通过上面不通过用例,但仍失败,由于i,j处并不是要找的值,发生死循环
class Solution {
public:
void quickselect(vector<int>& nums, int k, int l, int r)
{
int i = l - 1, j = r + 1, pivot = nums[l + r >> 1];
while (i < j){
do i++; while(nums[i] < pivot);
do j--; while(nums[j] > pivot);
if(i < j)swap(nums[i], nums[j]);
}
int sl = j - l -1;
if(sl == k) return;
if(sl > k) quickselect(nums, k, l, j-1);
if(sl < k) quickselect(nums, k- sl -1, j, r);
}
int findKthLargest(vector<int>& nums, int k) {
quickselect(nums, nums.size() - k, 0, nums.size() - 1);
return nums[nums.size() - k];
}
};
class Solution {
public:
void quickselect(vector<int>& nums, int k, int l, int r)
{
int i = l - 1, j = r + 1, pivot = nums[l + r >> 1];
while (i < j){
do i++; while(nums[i] < pivot);
do j--; while(nums[j] > pivot);
if(i < j)swap(nums[i], nums[j]);
}
if(j == k) return;
if(j > k) quickselect(nums, k, l, j);
if(j < k) quickselect(nums, k, j+1, r);
}
int findKthLargest(vector<int>& nums, int k) {
quickselect(nums, nums.size() - k, 0, nums.size() - 1);
return nums[nums.size() - k];
}
};
一定要循环到l==r
class Solution {
public:
void quickselect(vector<int>& nums, int k, int l, int r)
{
if(l == r) return;
int i = l - 1, j = r + 1, pivot = nums[l + r >> 1];
while (i < j){
do i++; while(nums[i] < pivot);
do j--; while(nums[j] > pivot);
if(i < j)swap(nums[i], nums[j]);
}
if(j >= k) quickselect(nums, k, l, j);
if(j < k) quickselect(nums, k, j+1, r);
}
int findKthLargest(vector<int>& nums, int k) {
quickselect(nums, nums.size() - k, 0, nums.size() - 1);
return nums[nums.size() - k];
}
};
此版本可以使用i > k,使用i≥k会出问题
class Solution {
public:
int quickselect(vector<int>& nums, int k, int l, int r)
{
if (l == r) return nums[k];
int i = l - 1 , j = r + 1 , pivot = nums[r];
while (i < j){
do j--; while(nums[j] > pivot);
do i++; while(nums[i] < pivot);
if(i < j)swap(nums[i], nums[j]);
}
if(i > k) return quickselect(nums, k, l, i-1);
return quickselect(nums, k, i, r);
}
int findKthLargest(vector<int>& nums, int k) {
return quickselect(nums, nums.size() - k , 0, nums.size() - 1);
}
};
ACwing版本修改
class Solution {
public:
int quickselect(vector<int>& nums, int k, int l, int r)
{
if (l == r) return nums[l];
int i = l - 1 , j = r + 1 , pivot = nums[l+r>>1];
while (i < j){
do i++; while(nums[i] < pivot);
do j--; while(nums[j] > pivot);
if(i < j)swap(nums[i], nums[j]);
}
int sl = j - l;
if(sl >= k) return quickselect(nums, k, l, j);
return quickselect(nums, k-sl-1, j+1, r);
}
int findKthLargest(vector<int>& nums, int k) {
return quickselect(nums, nums.size() - k, 0, nums.size() - 1);
}
};
class Solution {
public:
int quickselect(vector<int>& nums, int k, int l, int r)
{
if (l == r) return nums[l];
int i = l - 1 , j = r + 1 , pivot = nums[l+r>>1];
while (i < j){
do i++; while(nums[i] < pivot);
do j--; while(nums[j] > pivot);
if(i < j)swap(nums[i], nums[j]);
}
int sl = j - l + 1;
if(sl >= k) return quickselect(nums, k, l, j);
return quickselect(nums, k-sl, j+1, r);
}
int findKthLargest(vector<int>& nums, int k) {
return quickselect(nums, nums.size() - k + 1, 0, nums.size() - 1);
}
};
LeetCode 解法
class Solution {
public:
int quickselect(vector<int>& nums, int k, int l, int r)
{
if (l == r) return nums[l];
int i = l - 1 , j = r + 1 , pivot = nums[l+r>>1];
while (i < j){
do i++; while(nums[i] < pivot);
do j--; while(nums[j] > pivot);
if(i < j)swap(nums[i], nums[j]);
}
if(j >= k) return quickselect(nums, k, l, j);
return quickselect(nums, k, j+1, r);
}
int findKthLargest(vector<int>& nums, int k) {
return quickselect(nums, nums.size() - k , 0, nums.size() - 1);
}
};
总结:总体来说快速选择算法思想采用快速排序的分治思想,但是需要注意边界条件,以及最终返回值的选择