215. Kth Largest Element in an Array
问题:
求数组中第k大的元素。
Example 1: Input: nums = [3,2,1,5,6,4], k = 2 Output: 5 Example 2: Input: nums = [3,2,3,1,2,4,5,5,6], k = 4 Output: 4 Constraints: 1 <= k <= nums.length <= 10^4 -10^4 <= nums[i] <= 10^4
解法:priority_queue(优先队列,堆heap),quick sort(快速查找)+ binary search(二分查找)
解法一:priority_queue
建立元素总数==k的最小堆,堆顶元素为最小元素。
那么堆顶即为所求。
将数组元素依次入堆,当堆size超过k,则弹出最小元素。(不断淘汰,第k+1大的元素,一定不为所求)
代码参考:
1 class Solution { 2 public: 3 int findKthLargest(vector<int>& nums, int k) { 4 priority_queue<int, vector<int>, greater<int>> q;//minimal heap: top->minimal element 5 for(int n:nums) { 6 q.push(n); 7 if(q.size()>k) q.pop(); 8 } 9 return q.top(); 10 } 11 };
解法二:quick sort + binary search
- 快速排序的方法:
- 每次以第一个元素为标准,将小于标准的数放左边,大于标准的数放右边。
- 最后将标准元素放中间。(标准元素的位置:即是最终排序好的位置,固定)
因此我们每次排序后,求标准元素位置p==size-k?(从小到大排序,从后往前第k个元素的index)
- 如果是,则找到搜求。
- 若p>size-k:
- 那么,所求一定在p左边:接下来继续对 left~p-1 的元素进行快速排序。
- 若p<size-k:
- 那么,所求一定在p右边:接下来继续对 p+1~right 的元素进行快速排序。
♻️ 优化:由于快速排序依赖数组中 标准 的分布性,
为了防止极端情况,我们使用shuffle将数组打乱。
代码参考:
1 class Solution { 2 public: 3 int findKthLargest(vector<int>& nums, int k) { 4 int l=0,r=nums.size()-1; 5 shuffle(nums); 6 k=nums.size()-k; 7 while(l<=r) { 8 int p=partition(nums, l, r); 9 if(p<k) { 10 l=p+1; 11 } else if(p>k) { 12 r=p-1; 13 } else { 14 return nums[p]; 15 } 16 } 17 return -1; 18 } 19 int partition(vector<int>& nums, int l, int r) { 20 if(l==r) return l; 21 int pivot=nums[l]; 22 int i=l+1, j=r; 23 while(i<=j) { 24 if(nums[i]>pivot && nums[j]<pivot) { 25 swap(nums[i], nums[j]); 26 i++; 27 j--; 28 } else { 29 if(nums[i]<=pivot) i++; 30 if(nums[j]>=pivot) j--; 31 } 32 } 33 swap(nums[l], nums[j]);//j can reach l+1 34 return j; 35 } 36 void shuffle(vector<int>& nums) { 37 int n=nums.size(); 38 for(int i=0; i<n; i++) { 39 int k = i+rand()%(n-i); 40 swap(nums[i], nums[k]); 41 } 42 return; 43 } 44 };