力扣HOT100之堆:215. 数组中的第K个最大元素
这道题是大厂面试的高频面试题,昨天面网易互娱的时候被问到了这道题,无论是手撕快速排序代码还是面试口头描述思路,我们都需要熟练掌握快速排序的写法,在面试中为了求稳,我们需要掌握最简单,最易记的一种实现方式,这里我推荐这个博主的快慢指针方法,通俗易懂,牢记这种方法,面试中更容易将快速排序写出来。
再回到本题,本题是需要求出数组中第K
大的元素,因此我们并不需要将整个数组都进行快速排序,我们只需要将第K
大的元素找出来即可,我们与视频中保持一致,使用升序排列。因此我们在进行过一轮快速排序后,直接判断枢轴所在的下标为多少,如果枢轴所在的下标恰好为nums.size() - K
,则枢轴对应的元素恰好为数组中第K
大的元素,我们直接将其赋值给result
即可。若枢轴对应的下标大于nums.size() - K
,那我们只需要对枢轴左侧的区间进行排序,右侧不需要管。若枢轴对应的下标小于nums.size() - K
,那我们只需要对枢轴右侧的区间进行排序,左侧不需要管。
下面简单描述一下单次快速排序的过程:
- 对于待排序区间,我们将快指针
fast
和慢指针slow
同时指向区间的第一个元素,枢轴指向区间的最后一个元素。 - 当
fast
指向的元素大于等于枢轴元素时,则fast
向右移动一位,slow
保持不动;当fast
指向的元素小于枢轴元素时,则先交换slow
和fast
指向的元素,再同时将fast
和slow
右移一位。 - 当
fast
到达枢轴指向的元素时,循环结束,此时还需要交换slow
和枢轴指向的元素,此时,slow
指向的元素为枢轴,slow
左侧的元素都小于nums[slow]
,右侧的元素都大于等于nums[slow]
,此时一轮排序结束。
下面是对应的代码,但是程序耗时太长了,这真的叫快速排序吗😂我怎么觉得是慢速排序呢
class Solution {
public:int result;int findKthLargest(vector<int>& nums, int k) {quicksort(nums, 0, nums.size() - 1, k);return result;}void quicksort(vector<int>& nums, int begin, int end, int k){int pivot = nums[end]; //总是选取区间的最后一个元素作为枢轴int slow = begin, fast = begin; //初始化快慢指针while(fast < end){if(nums[fast] >= pivot) //快指针元素大于等于枢轴则快指针右移fast++;else{swap(nums[slow], nums[fast]);slow++;fast++;}}swap(nums[slow], nums[end]); //交换慢指针与枢轴所指的元素if(slow > nums.size() - k) //需要向左查找quicksort(nums, begin, slow - 1, k);else if(slow < nums.size() - k) //需要向右查找quicksort(nums, slow + 1, end, k);else{ //找到第k大的元素了result = nums[slow];return ;}}
};