排序小结

215. 数组中的第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 ≤ 数组的长度。

题解:

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);
    }
};

希尔、基数排序待补……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值