2020年9月2日 周三 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
215. 数组中的第K个最大元素 雷同题目: 剑指offer 40. 最小的k个数(经典TopK问题)
另外很重要的一点就是,partition()分割函数用循环覆盖的方法实现的话,虽然很巧妙,但是比较难想,特别是在面试时需要手撕代码的时候,很容易一紧张就忘了,所以下面给出常规思路:把小于 pivot 的元素都交换到前面,最后再把 pivot 的值交换到中间。 具体代码如下:
class Solution { public: int findKthLargest(vector<int>& nums, int k) { // 设置随机数种子 srand(time(0)); int len = nums.size(); int target = len - k; int l = 0, r = len - 1; while(true){ int idx = partition(nums,l,r); if(idx==target) break; else if(idx>target) r = idx - 1; else l = idx + 1; } return nums[target]; } // 分割操作常规思路(以中轴元素为基准,将数组分割成三部分,返回中轴元素索引) int partition(vector<int>& nums, int l, int r){ int rand_idx = rand()%(r-l+1)+l; swap(nums[l], nums[rand_idx]); int pivot = nums[l]; // j 的初始位置为 l,并且在循环的过程中,始终保持 nums[j] <= pivot int j = l; for(int i=l+1;i<=r;++i){ // 小于 pivot 的元素都被交换到前面 if(nums[i]<pivot){ ++j; swap(nums[i],nums[j]); } } swap(nums[l],nums[j]); return j; } };本题也可以用最小堆:根据数组前 k 个元素建立一个大小为 k 的最小堆,然后遍历剩下的数组元素,与堆顶元素进行比较,动态调整堆中的元素,数组遍历结束后的堆中元素就是数组中前 k 大的元素,堆顶元素是堆中最小元素,也就是第 k 大的元素。
class Solution { public: int findKthLargest(vector<int>& nums, int k) { // 复制数组前k个元素到堆中 vector<int> minHeap(nums.begin(), nums.begin()+k); // 调整为最小堆 for(int i=k/2-1;i>=0;--i){ minHeapAdjustDown(minHeap,i,k); } // 从第k+1个元素开始遍历数组,将数组元素与堆顶元素进行比较 for(int i=k;i<nums.size();++i){ // 大于堆顶元素,则替换之 if(nums[i]>minHeap[0]){ swap(nums[i],minHeap[0]); minHeapAdjustDown(minHeap,0,k); } } // 遍历结束后,堆顶元素即为第k大元素 return minHeap[0]; } // 最小堆向下调整(常用于删除元素) void minHeapAdjustDown(vector<int>& minHeap, int parent, int len) { int child = 2 * parent + 1; int num = minHeap[parent]; while (child < len) { if (child + 1 < len && minHeap[child + 1] < minHeap[child]) ++child; if (num > minHeap[child]) { minHeap[parent] = minHeap[child]; parent = child; child = 2 * parent + 1; } else break; } minHeap[parent] = num; } };也可以用STL中的优先队列priority_queue 来实现,这里就不详细写了。
借助STL中的mutilset来实现,过程和使用priority_queue 实现很像,这里也不详细写了。另外,虽然第二种方法时间复杂度更高,但是更适合用于海量数据,所以这两种方法各有优劣,海量数据的TopK问题可以参考这篇文章:【面试现场】如何在10亿数中找出前1000大的数。
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/shu-zu-zhong-de-di-kge-zui-da-yuan-su-by-leetcode-/