<leetcode每日一题>数组中的第K个最大元素
题目描述:
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
思路分析:这道题第一次看到类似的题是在算法设计与分析这本书的第三章分治策略,当时书上给的方法是以中位数为基准进行第K小元素的查找,还记得若采取这样的方法,则算法的效率取决于分治分组的元素个数阈值。第二次见到是在随机算法这一章,利用舍伍德随机算法优化原算法。在选择以中位数作为基准时,原算法比较次数T(n)<=80n,利用随机算法优化过后,比较次数可以达到n<=T(n)<=4n,在输入规模大的情况下平均性能会比原算法要好
这个优化算法简单的来说,就是随机选取划分基准x,将数组的元素按照与基准x大小的关系划分为A1,A2,A3,对于任意的a属于数组,若a<x则将a放入A1,a=x则将a放入A2,若a>x则将a放入A3,之后比较A1,A2,A3这三个子数组的大小,如果A1.size大于k,则说明第k小元素在A1中,递归调用函数并传入A1和k,如果A1.size+A2.size>=k则说明x就是第k小元素,返回x,否则第k小元素一定在A3数组中,继续递归查找。
代码如下:
1 class Solution { 2 public: 3 int RandomSelect(vector<int>&nums,int k){ 4 vector<int>A1; 5 vector<int>A2; 6 vector<int>A3; 7 srand((unsigned)time(NULL)); 8 int a = 1,b = nums.size(); 9 int v = (rand()%b)+1; 10 int x = nums[v-1]; 11 for(int i = 0;i<b;i++){ 12 if(nums[i]<x){ 13 A1.push_back(nums[i]); 14 } 15 else if(nums[i]>x){ 16 A3.push_back(nums[i]); 17 } 18 else A2.push_back(nums[i]); 19 } 20 if(A1.size()>=k){ 21 return RandomSelect(A1,k); 22 } 23 else if((A1.size()+A2.size())>=k){ 24 return x; 25 } 26 else if((A1.size()+A2.size())<k) return RandomSelect(A3,k-A1.size()-A2.size()); 27 return -2; 28 } 29 int findKthLargest(vector<int>& nums, int k) { 30 int res = RandomSelect(nums,nums.size()-k+1); 31 return res; 32 } 33 };