题目:
Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
For example,
Given [3,2,1,5,6,4]
and k = 2, return 5.
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.
题意:
从一个未经排序的数组中找出第k大的元素。注意是排序之后的第k大,而非第k个不重复的元素。
转载地址:https://discuss.leetcode.com/topic/15256/4-c-solutions-using-partition-max-heap-priority_queue-and-multiset-respectively
思路一:
最简单的解决方法就是直接将给定的数组按递减顺序排序,然后返回k-1下标处的元素即可。
代码:C++版:20ms
class Solution { public: int findKthLargest(vector<int>& nums, int k) { int len = nums.size(); sort(nums.begin(), nums.end()); return nums[len-k]; } };
思路二:
分析:以上思路是先将数组排序,时间复杂度是O(nlogn),但是如果给定的数组非常大n=1000,而k值很小k=2时,以上算法就做了很多不必要的计算操作。
分治法。快速排序:以给定数组的第一个值作为分隔点,轮训一遍给定数组,将大于该值的部分放到左边,小于该值的部分放到右边,轮训结束,该值左边的数组值均比该值大,故可以确定该值目前在数组中是第几大的值,每次循环将该值返回与目标大小进行对比,利用对比结果改变left和right初始值,继续进行下一轮分割循环,直到找到第k大的原值值即可。
代码:C++版:212ms
class Solution { public: int findKthLargest(vector<int>& nums, int k) { int left = 0, right = nums.size()-1; while (true) { int pos = partition(nums, left, right); if (pos == k-1) return nums[pos]; if (pos > k-1) //说明目标值在数组左部分 right = pos - 1; else //说明目标值在数组右部分 left = pos + 1; } } //以nums数组第一个值作为分割点,大于该值的在数组左边,小于的部分在数组右边 int partition(vector<int>& nums, int left, int right) { int pivot = nums[left]; int l = left + 1, r = right; while (l <= r) { if (nums[l] < pivot && nums[r] > pivot) swap(nums[l++], nums[r--]); if (nums[l] >= pivot) l++; if (nums[r] <= pivot) r--; } swap(nums[left], nums[r]); return r; //返回该值的位置 } };
思路三:
利用堆排序思路,堆排序步骤如下:
1、基于nums数组构建max_heap,并设置heap_size的值为与数组长度大小相同;
2、交换nums[0]与nums[heap_size-1],因为完成max_heap构建之后,nums[0]处保存的是给定数组nums中最大的元素,然后将heap_size减1,将数组下标回送到0处,开始下一轮处理;
3、重复步骤2一共k次,并且第k大的数被保存在nums[heap_size]中。
代码:C++版:20ms
class Solution { private: int heap_size; public: inline int left(int idx) { return (idx << 1) + 1; } inline int right(int idx) { return (idx << 1) + 2; } void max_heapify(vector<int>& nums, int idx) { int largest = idx; int l = left(idx), r = right(idx); if (l < heap_size && nums[l] > nums[largest]) largest = l; if (r < heap_size && nums[r] > nums[largest]) largest = r; if (largest != idx) { swap(nums[idx], nums[largest]); max_heapify(nums, largest); } } void build_max_heap(vector<int>& nums) { heap_size = nums.size(); for (int i = (heap_size >> 1) - 1; i >= 0; i--) max_heapify(nums, i); } int findKthLargest(vector<int>& nums, int k) { build_max_heap(nums); for (int i = 0; i < k; i++) { swap(nums[0], nums[heap_size - 1]); heap_size--; max_heapify(nums, 0); } return nums[heap_size]; } };
如果允许使用内建函数priority_queue,代码会简单很多。
代码:C++版:24ms
class Solution { public: int findKthLargest(vector<int>& nums, int k) { priority_queue<int> pq(nums.begin(), nums.end()); for (int i=0; i<k-1; i++) pq.pop(); return pq.top(); } };也可以使用multiset替代priority_queue实现。
代码:C++版:28ms
class Solution { public: int findKthLargest(vector<int>& nums, int k) { multiset<int> mset; int n = nums.size(); for (int i=0; i<n; i++) { mset.insert(nums[i]); if (mset.size() > k) mset.erase(mset.begin()); } return *mset.begin(); } };