数组中的第K个最大元素、堆排序、快速排序、归并排序详解

该博客介绍了如何使用大根堆来解决在未排序数组中找到第K个最大元素的问题。首先,通过大根堆调整数组,然后从最后一个元素开始遍历,返回倒数第K个元素作为结果。这种方法的时间复杂度为O(nlogn),适用于寻找排序后的第K大元素。
摘要由CSDN通过智能技术生成

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 ≤ 数组的长度。尽量采用o(nlogn)复杂度的排序算法,取数组中序号为nums.size()-k的数即为第k个最大的数。代码需要天天练习,继续刚

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        // quicks(nums,0,nums.size());
        // solve(nums,0,nums.size()-1);
        // for(int i=nums.size()/2-1;i>=0;--i){
        //     dui(nums,i);
        // }
        for(int i=nums.size()/2-1;i>=0;--i)
        dui(nums,i,nums.size());


        for(int i=nums.size()-1;i>0;--i){
            int temp= nums[0];
            nums[0] = nums[i];
            nums[i] = temp;
            dui(nums,0,i);
        }

        return nums[nums.size()-k];
    }


// 新加入节点i  大根堆
    void dui(vector<int>&nums,int i,int len){
// len代表在[0,len)上满足大根堆
        int temp= nums[i];
        // 保存要调整的值,等会儿要交换
        // k先设置为i的左儿子
        for(int k=2*i+1;k<len;k=2*k+1  ){
            if(k+1<len&&nums[k]<nums[k+1]){
                // k保存i的两个儿子中大的节点的序号
                k++;
            }
            if(temp<nums[k]){
                nums[i] = nums[k];
                i=k;
            }
            else break;
        }
        nums[i] = temp;

    }

// // 新加入节点i  大根堆
//     void dui(vector<int>&nums,int i,int len){
// // len代表在[0,len]上满足大根堆
//         int temp= nums[i];
//         // 保存要调整的值,等会儿要交换
//         // k先设置为i的左儿子
//         for(int k=2*i+1;k<=len;k=2*k+1  ){
//             if(k+1<=len&&nums[k]<nums[k+1]){
//                 // k保存i的两个儿子中大的节点的序号
//                 k++;
//             }
//             if(temp<nums[k]){
//                 nums[i] = nums[k];
//                 i=k;
//             }
//             else break;
//         }
//         nums[i] = temp;

//     }



// 归并排序 将a[first,mid] a[mid+1,last] 合并


    // void mergearray(vector<int>&a,int first,int mid,int end){
    //     vector<int>temp(end+1);
    //     int i=first,k=mid+1;
    //     // 两个待合并数组的起点
    //     int p=0;
    //     // 小的先放在临时数组里面
    //     while(i<=mid&&k<=end){
    //         if(a[i]<a[k]){
    //             temp[p] = a[i];
    //             p++,i++;
    //         }
    //         else if(a[i]>=a[k]){
    //             temp[p] = a[k];
    //             p++,k++;
    //         }

    //     }
    //     // 把剩余部分依次放到临时数组里面
    //     while(i<=mid){
    //         temp[p] = a[i];
    //         p++,i++;
    //     }
    //     while(k<=end){
    //         temp[p] = a[k];
    //         p++,k++;
    //     }
    //     // 把临时数组里面已经有序的元素拷贝回来
    //     for(int j=0;j<p;++j){
    //         a[first+j] = temp[j];
    //     }
    //     temp.clear();
    // }
    // void solve(vector<int>&nums,int first,int last){
    //     // 排序区间是【】  first==last时不用排序
    //     if(first<last){
    //         int mid = (first+last)/2;
    //         // 左边有序
    //         solve(nums,first,mid);
    //         // 右边有序
    //         solve(nums,mid+1,last);
    //         // 合并
    //         mergearray(nums,first,mid,last);
    //     }
    // }



// 快速排序
//     void quicks(vector<int>&nums,int start,int end ){
//         // 排序区间为[start,end)
//         if(start<end){
//         int i = start;
//         int j = end-1;
//         int flag = nums[start];
//         // 取枢纽值,比较标准值
       
//         while(i<j){
//              // 从右往左找比flag小的数,保存到nums[i]中
//             while(nums[j]>=flag&&i<j) j--;
//             nums[i] = nums[j];

// // 从左往右找比flag大的数,保存到num[j]中
//             while(nums[i]<flag&&i<j) i++;
//             nums[j] = nums[i];
//         }
//         nums[i] = flag;


//         quicks(nums,start,i);
//         quicks(nums,i+1,end);

//         }

        

//     }


    // void quicks(vector<int>&nums,int fir,int end){
    //     int i=fir,j=end;
    //     int x = nums[i];
    //     if(fir>=end) return ;
    //     // int temp;
    //     while(i<j){
    //        while(nums[j]>=x&&i<j) j--;
    //        nums[i] = nums[j];
    //        while(nums[i]<=x&&i<j) i++;
    //         nums[j] = nums[i];
    //     }
    //     nums[i] = x;
    //     if(fir<i)
    //     quicks(nums,fir,i-1);
    //     if(i<end)
    //     quicks(nums,i+1,end);
        

    // }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值