在未排序的数组中找到第 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 ≤ 数组的长度。
题解:
1.建立一个长度为K的最小堆,返回对顶元素(8ms左右);
class Solution {
public:
vector<int>b;
int len;
void init(){ // 建堆
int i=b.size()-1;
while(i>=1){
int j=i%2==0?(i/2-1):(i/2);
if(b[j]>b[i]){
swap(b[i],b[j]);
i=j;
}
else break;
}
}
void pushup(int x){ // 向下更新
if(x<b[0]) return ;
b[0]=x;
int i=0;
while(i<b.size()){
int j=i*2+1,k=i*2+2,d=i;
if(j<b.size()) d=j;
if(k<b.size()) d=b[j]<=b[k]?j:k;
if(b[d]<b[i]){
swap(b[i],b[d]);
i=d;
}
else break;
}
}
int findKthLargest(vector<int>& a, int k) {
for(int i=0;i<k;i++){
b.push_back(a[i]);
init();
}
init();
for(int i=k;i<a.size();i++)
pushup(a[i]);
return b[0];
}
};
2.利用快排思想解决(36ms左右):
class Solution {
public:
int ans=0;
void dfs(vector<int>& a,int k,int l,int r){
if(l>=r){
if((a.size()-l)==k)
ans=a[l];
return ;
}
int x=a[l],i=l,j=r;
while(j>i){
while(a[j]>=x&&j>i) j--;
while(a[i]<=x&&j>i) i++;
if(i!=j) swap(a[i],a[j]);
else break;
}
swap(a[l],a[i]);
if((a.size()-i)==k){ // 一次次的进行划分,直到划分成功
ans=a[i];
return ;
}
if(k<(a.size()-i)) dfs(a,k,i+1,r);
else dfs(a,k,l,i-1);
}
int findKthLargest(vector<int>& a, int k) {
dfs(a,k,0,a.size()-1);
return ans;
}
};
3.利用C++的快排库函数(12ms左右)
class Solution {
public:
static bool cmp(int x,int y){
return x>y;
}
int findKthLargest(vector<int>& a, int k) {
sort(a.begin(),a.end(),cmp);
return a[k-1];
}
};
4.利用C++的优先队列,底层也是堆(16ms左右)
class Solution {
public:
struct cmp{
bool operator()(int &x,int &y)const{
return x>y;
}
};
int findKthLargest(vector<int>& a, int k) {
priority_queue<int,vector<int>,cmp>q;
int num=0;
for(int i=0;i<a.size();i++){
q.push(a[i]);
num++;
if(k<num) q.pop();
}
return q.top();
}
};
5.冒泡排序(1100ms左右)
class Solution {
public:
void work(vector<int>& a){ // 冒泡
for(int i=0;i<a.size()-1;i++){
for(int j=1;j<a.size();j++){
if(a[j]>a[j-1]) swap(a[j],a[j-1]);
}
}
}
int findKthLargest(vector<int>& a, int k) {
work(a);
return a[k-1];
}
};
6.选择排序(640ms左右)
class Solution {
public:
void work(vector<int>& a){ // 选择
for(int i=0;i<a.size();i++){
for(int j=i+1;j<a.size();j++){
if(a[i]<a[j]) swap(a[i],a[j]);
}
}
}
int findKthLargest(vector<int>& a, int k) {
work(a);
return a[k-1];
}
};
7.插入排序(300ms左右)
class Solution {
public:
void work(vector<int>& a){ // 插入
for(int i=0;i<a.size();i++){
int x=a[i];
for(int j=i-1;j>=0;j--){
if(a[j]<x) swap(a[j],a[j+1]);
else{
a[j+1]=x;
break;
}
}
}
}
int findKthLargest(vector<int>& a, int k) {
work(a);
return a[k-1];
}
};
8.手写快速排序(120ms左右)
class Solution {
public:
void work(vector<int>& a,int l,int r){ // 快排
if(l>=r) return ;
int i=l,j=r,x=a[l];
while(i<j){
while(a[j]>=x&&j>i) j--;
while(a[i]<=x&&j>i) i++;
if(i!=j) swap(a[i],a[j]);
else break;
}
swap(a[l],a[i]);
work(a,l,i-1);
work(a,i+1,r);
}
int findKthLargest(vector<int>& a, int k) {
work(a,0,a.size()-1);
return a[a.size()-k];
}
};
9.归并排序(12ms左右),由此可见,上边的快排写丑了,尴尬!
class Solution {
public:
vector<int>b;
void work(vector<int>& a,int l,int r){ // 归并
if(l==r) return ;
int mid=l+r>>1;
work(a,l,mid);
work(a,mid+1,r);
int i=l,j=mid+1,p=l;
while(i<=mid&&j<=r){
if(a[i]<=a[j])
b[p++]=a[i++];
else
b[p++]=a[j++];
}
while(i<=mid) b[p++]=a[i++];
while(j<=r) b[p++]=a[j++];
for(i=l;i<=r;i++) a[i]=b[i];
}
int findKthLargest(vector<int>& a, int k) {
for(int i=0;i<a.size();i++) b.push_back(0);
work(a,0,a.size()-1);
return a[a.size()-k];
}
};
10.堆排序(12ms左右)
class Solution {
public:
void init(vector<int>& a,int n){ // 建堆
int i=n;
while(i>=1){
int j=i%2==0?(i/2-1):(i/2);
if(a[j]<a[i]){
swap(a[j],a[i]);
i=j;
}
else break;
}
/*
for(int i=n;i>=1;i--){
int j=i%2==0?(i/2-1):(i/2);
if(a[j]<a[i]) swap(a[j],a[i]);
}*/
}
void pushup(vector<int>& a,int len){ // 更新
int i=0;
while(i<len){
int j=i*2+1,k=i*2+2,d=i;
if(j<len) d=j;
if(k<len&&a[k]>a[j]) d=k;
if(a[d]>a[i]){
swap(a[i],a[d]);
i=d;
}
else break;
}
}
void work(vector<int>& a){ // 堆排
for(int i=a.size()-1;i>=1;i--){
swap(a[0],a[i]);
pushup(a,i-1);
}
}
int findKthLargest(vector<int>& a, int k) {
int len=a.size();
for(int i=0;i<len;i++) init(a,i);
work(a);
return a[a.size()-k];
}
};
10.简单桶排(50ms左右)
class Solution {
public:
static const int N=5e+5;
int num1[N],num2[N]; // num1[] 存正数,num2[] 存负数
int work(vector<int>& a,int k){ // 简单的桶排实现
for(int i=0;i<a.size();i++){
if(a[i]>=0) num1[a[i]]++;
else num2[abs(a[i])]++;
}
int ans=0,leap=0;
for(int i=N-1;i>=0;i--){
if(num1[i]){
if(num1[i]>=k) { leap=1;ans=i;break; }
else k-=num1[i];
}
}
if(leap)
return ans;
for(int i=1;i<N;i++){
if(num2[i]){
if(num2[i]>=k) { ans=-i;break; }
else k-=num2[i];
}
}
return ans;
}
int findKthLargest(vector<int>& a, int k) {
return work(a,k);
}
};
希尔、基数排序待补……