这题用了快排的思想,思路如下:
数组从小到大排序思想更为直观,所以一开始先k = n-k
1)选一个pivot,然后把pivot放在合适的位置,也就是快排的Partion操作,把小于pivot的放前面,大于pivot的放后面。
2)如果pivot的位置等于k,则返回pivot
3)如果pivot的位置大于k,则证明要找的数在pivot前面,否则在后面,然后递归就可以了。
特别的,如果left == right,直接返回就可以,也不用找pivot了
这里的下标非常容易出错,有两个版本:
第一个版本
class Solution {
public:
int find(vector<int> &nums, int left, int right, int k){
if(left == right)
return nums[left];
int i = left, j = right;
int pivot = nums[left];
while(i < j){
while(nums[i] <= pivot && i < right) i++;
while(nums[j] > pivot && left < j) j--;
if(i < j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
int ind = j;
int tmp = nums[ind];
nums[ind] = nums[left];
nums[left] = tmp;
if(ind == k){
return nums[ind];
} else if(ind > k){
return find(nums, left, ind - 1, k);
} else {
return find(nums, ind + 1, right, k);
}
}
int findKthLargest(vector<int>& nums, int k) {
return find(nums, 0, nums.size() - 1, nums.size() - k);
}
};
第二个版本
class Solution {
public:
int find(vector<int> &nums, int left, int right, int k){
if(left == right)
return nums[left];
int i = left + 1, j = right;
int pivot = nums[left];
while(i != j){
while(nums[i] <= pivot && i < j) i++;
while(nums[j] > pivot && i < j) j--;
if(i != j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
int ind = (nums[i] > pivot) ? i - 1 : i;
int tmp = nums[ind];
nums[ind] = nums[left];
nums[left] = tmp;
if(ind == k){
return nums[ind];
} else if(ind > k){
return find(nums, left, ind - 1, k);
} else {
return find(nums, ind + 1, right, k);
}
}
int findKthLargest(vector<int>& nums, int k) {
return find(nums, 0, nums.size() - 1, nums.size() - k);
}
};
可以看到, i和j的含义都不一样,但是最后都能得到正确的答案。我认为第二种比较直观。