给定一个整数数组,返回数组的第k个最大的元素。
(1)很容易能想到,可以先对数组进行排序,排序之后,nums[size - k ]就是想要的结果。排序算法可以使用选择排序、交换排序、插入排序、堆排序、快速排序、归并排序。前3种排序算法的时间复杂度为O(n * n),后3种排序算法的事件复杂度是O(nlogn)。在实际使用中,常常使用堆排序或者快速排序,堆排序是选择排序的思想,快速排序是交换排序的思想。
(2)使用堆排序或者快速排序,需要把数组整体排序完成吗?不需要
因为题目要求查找第k个最大的数,如果使用堆排序,那么进行k次选择就可以得到结果。如果使用快速排序,快速排序使用了二分法和递归的思想,每次运算都能确定二分的这个点的位置,如果这个点的位置正好是size - k的位置,那么这个位置就是题目的结果,此时就可以停止排序。
1堆排序
cpp
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
createInitialHeap(nums);
for (int i = 0; i < k; i++) {
int tmp = nums[0];
nums[0] = nums[nums.size() - i - 1];
nums[nums.size() - i - 1] = tmp;
adjustHeap(nums, 0, nums.size() - i - 1 - 1);
}
return nums[nums.size() - k];
}
void createInitialHeap(vector<int>& nums) {
int mid = nums.size() / 2;
for (int i = mid; i >= 0; i--) {
adjustHeap(nums, i, nums.size() - 1);
}
}
void adjustHeap(vector<int>& nums, int start_index, int end_index) {
if (start_index >= end_index) {
return;
}
int bigger_index = start_index;
int left_child_index = start_index * 2 + 1;
int right_child_index = left_child_index + 1;
if (left_child_index <= end_index && nums[left_child_index] > nums[bigger_index]) {
bigger_index = left_child_index;
}
if (right_child_index <= end_index && nums[right_child_index] > nums[bigger_index]) {
bigger_index = right_child_index;
}
if (bigger_index != start_index) {
int tmp = nums[start_index];
nums[start_index] = nums[bigger_index];
nums[bigger_index] = tmp;
adjustHeap(nums, bigger_index, end_index);
}
}
};
2快速排序
cpp
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
quickSort(nums, 0, nums.size() - 1, k);
return nums[nums.size() - k];
}
void quickSort(vector<int> &nums, int left, int right, int k) {
if (left >= right) {
return;
}
int select_value = nums[left];
int tmp_left = left;
int tmp_right = right;
while (tmp_left < tmp_right) {
while (tmp_right > tmp_left && nums[tmp_right] > select_value) {
tmp_right--;
}
if (tmp_right > tmp_left) {
nums[tmp_left] = nums[tmp_right];
tmp_left++;
}
while (tmp_left < tmp_right && nums[tmp_left] < select_value) {
tmp_left++;
}
if (tmp_left < tmp_right) {
nums[tmp_right] = nums[tmp_left];
tmp_right--;
}
}
nums[tmp_left] = select_value;
if (tmp_left == nums.size() - k) {
return;
} else if (tmp_left < nums.size() - k) {
quickSort(nums, tmp_left + 1, right, k);
} else {
quickSort(nums, left, tmp_left - 1, k);
}
}
};