/*
具体方法:使用类似快速排序,执行一次快速排序后,
每次只选择一部分继续执行快速排序,直到找到第K个大元素为止,
此时这个元素在数组位置后面的元素即所求
时间复杂度:
若随机选取枢纽,线性期望时间O(N)
若选取数组的“中位数的中位数”作为枢纽,最坏情况下的时间复杂度O(N)
利用快速排序的思想,从数组S中随机找出一个元素X,把数组分为两部分Sa和Sb。
Sa中的元素大于等于X,Sb中元素小于X。这时有两种情况:
1. Sa中元素的个数小于k,则Sb中的第k-|Sa|个元素即为第k大数;
2. Sa中元素的个数大于等于k,则返回Sa中的第k大数。
利用快排的partion思想 T(n) = 2T(n/2) + O(1) 时间复杂度为O(n)
该方法只有当我们可以修改输入的数组时可用,
位于数组左边的k个数字就是最小的k个数字(但这k个数字不一定是排序的),
位于第k个数右边的数字都比第k个数字大
*/
#include <iostream>
#include <vector>
using namespace std;
int Partition(vector<int> &v,int left,int right){
int tmp=v[left];
while(left<right){
while(left<right&&v[right]<=tmp) right--;
v[left]=v[right];
while(left<right&&v[left]>=tmp) left++;
v[right]=v[left];
}
v[left]=tmp;
return left;
}
int findk(int k,vector<int> v,int left,int right){
int mid=Partition(v,left,right);
if(mid==k-1) return v[mid];
else if(mid<k-1) return findk(k,v,mid+1,right);
else return findk(k,v,left,mid-1);
}
int main(){
int k;
while(1){
vector<int> v={15,25,9,48,36,100,58,99,126,5};
int len=v.size();
cout<<"排序前:"<<endl;
for(int k:v) cout<<k<<" ";
cout<<endl;
cout<<"请输入你要查找第k大的数:"<<endl;
cin>>k;
int kth=findk(k,v,0,len-1); //查找第k大的数
cout<<"第"<<k<<"大数:"<<kth<<endl;
cout<<endl;
}
return 0;
}
确定N个数中的第k大元素-数据结构与算法分析-C语言描述 Mark Allen Weiss-第一章练习题
最新推荐文章于 2022-05-28 10:58:29 发布