数组中的第K个最大元素
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
code1:堆排序
class Solution { public: int findKthLargest(vector<int>& nums, int k) { if(nums.empty()||k<=0||nums.size()<k) return 0; make_heap(nums.begin(),nums.end()); while(k!=1) { pop_heap(nums.begin(),nums.end()); nums.pop_back(); --k; } return nums[0]; } };
code2: bfprt
class Solution { public: int findKthLargest(vector<int>& nums, int k) { if(nums.empty()||k<0||k>nums.size()) return 0; vector<int> tmp(nums.begin(),nums.end()); return bfprt(tmp,0,tmp.size()-1,tmp.size()-k); } private: int bfprt(vector<int>& arr,int left,int right,int k) { if(left==right) return arr[left]; //1.得到中位数 int pivot=getMedian(arr,left,right); //2.根据中位数划分左右区间 vector<int> pivotRange=_partition(arr,left,right,pivot); //3.找到中位数排序后的位置,判断k是不是中位数所在的下标范围内,如果在就找到了 if(k>=pivotRange[0]&&k<=pivotRange[1]) return arr[k]; else if(k<pivotRange[0]) return bfprt(arr,left,pivotRange[0]-1,k); else /*if(k>pivotRange[1])*/ return bfprt(arr,pivotRange[1]+1,right,k); } int getMedian(vector<int>& arr,int left,int right) { int nums=right-left+1; int offset=nums%5==0?0:1;//每五个为一组,求每组的中位数,放在中位数数组中 vector<int> midArr(nums/5+offset);//中位数数组 for(int i=0;i<midArr.size();++i) { int l=left+i*5; int r=l+4; midArr[i]=getMedianCore(arr,l,min(r,right)); } //找中位数组的中位数 return bfprt(midArr,0,midArr.size()-1,midArr.size()/2); } int getMedianCore(vector<int>& arr, int left, int right) { //中位数组排序,返回中间数 sort(arr.begin()+left,arr.begin()+right+1); return arr[(left+right)/2+(left+right)%2];//奇数和偶数情况 } vector<int> _partition(vector<int>& arr,int left,int right,int pivot) { int small=left-1; int big=right+1; int cur=left; while(cur<big) { if(arr[cur]<pivot) swap(arr[++small],arr[cur++]); else if(arr[cur]>pivot) swap(arr[cur],arr[--big]); else ++cur; } vector<int> tmp{small+1,big-1}; return tmp; } };