堆----1.数组中的第K个最大元素

215. 数组中的第K个最大元素 - 力扣(LeetCode)

/**

第一大元素--->len - 1

第二大元素--->len - 2

.......

第K大元素---->len - K,则数组中第K个最大元素,转化为寻找排序后第len - K位置的元素

快速选择算法:

快速排序的变种,核心的分区函数一致,在数组中随机选择一个基准 pivot

按基准将数组划分为三个部分 小于基准 基准 大于基准,那么此时基准所在的位置就是排序后该在的位置

变种:

在本题中,若划分后基准所在位置恰好是len - k,那么说明基准就是第K个最大元素

若基准 < len - K, 则减小范围,在基准 + 1,right中重新选择基准,重复上述流程

若基准 > len - K, 则减小范围,在left, 基准 - 1中重新选择基准,重复上述流程

直到找到为止

分区函数(核心):

首先在数组中随机选择一个元素为基准元素,从左右两端同时开始扫描

左指针向右遍历,直到遇到第一个>=pivot的元素

右指针向左遍历,直到遇到第一个<=pivot的元素

交换左右指针的值,交换后,大于基准元素的在右半区,小于基准元素的在左半区,等于基准元素的平均分布在左、右半区

细节注意:

在选择出基准元素后,将其移至数组首位

遍历完毕后基准元素与左指针交换位置,将基准元素移动至正确位置

*/

java 复制代码
class Solution {
    /**
        第一大元素--->len - 1
        第二大元素--->len - 2
        .......
        第K大元素---->len - K,则数组中第K个最大元素,转化为寻找排序后第len - K位置的元素
        快速选择算法:
                    快速排序的变种,核心的分区函数一致,在数组中随机选择一个基准 pivot
                    按基准将数组划分为三个部分 小于基准 基准 大于基准,那么此时基准所在的位置就是排序后该在的位置
                变种:
                    在本题中,若划分后基准所在位置恰好是len - k,那么说明基准就是第K个最大元素
                    若基准 < len - K, 则减小范围,在[基准 + 1,right]中重新选择基准,重复上述流程
                    若基准 > len - K, 则减小范围,在[left, 基准 - 1]中重新选择基准,重复上述流程
                    直到找到为止
                分区函数(核心):
                    首先在数组中随机选择一个元素为基准元素,从左右两端同时开始扫描
                    左指针向右遍历,直到遇到第一个>=pivot的元素
                    右指针向左遍历,直到遇到第一个<=pivot的元素
                    交换左右指针的值,交换后,大于基准元素的在右半区,小于基准元素的在左半区,等于基准元素的平均分布在左、右半区
                细节注意:
                    在选择出基准元素后,将其移至数组首位
                    遍历完毕后基准元素与左指针交换位置,将基准元素移动至正确位置
    */

    private int[] nums;
    private int target;
    private final Random random = new Random();

    public int findKthLargest(int[] nums, int k) {
        this.nums = nums;
        this.target = nums.length - k;

        quickSelect(0,nums.length - 1);
        return nums[target];
    }

    //快速选择
    private void quickSelect(int left, int right) {
        if(left > right) {
            return;
        }

        int pivotIndex = partition(left, right); //得到第一个有序的位置

        if(pivotIndex == target) { 
            return;
        } else if(pivotIndex < target) {
            quickSelect(pivotIndex + 1, right); //[基准 + 1,right]
        } else {
            quickSelect(left,pivotIndex - 1); //[left, 基准 - 1]
        }
    }

    //分区函数
    private int partition(int left, int right) {
        //生成随机基准
        int pivot = random.nextInt(right - left + 1) + left;
        int pivotValue = nums[pivot];
        swap(left,pivot); //先将基准移至首位

        //双端同时开始扫描
        int le = left + 1;
        int ge = right;
        
        while(true) {
            //左指针向右遍历,直到遇到第一个>=pivot的元素
            while(le <= ge && nums[le] <pivotValue) {
                le++;
            }

             //右指针向左遍历,直到遇到第一个<=pivot的元素
            while(le <= ge && nums[ge] > pivotValue) {
                ge--;
            }

            //遍历结束退出
            if(le >= ge) {
                break;
            }

            //交换两指针的值,进行分区
            swap(le,ge);
            le++;
            ge--;

        }

        //遍历完毕后基准元素与左指针交换位置,将基准元素移动至正确位置
        swap(left,ge);
        return ge;
    }

    private void swap(int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
}
相关推荐
lhldsg9 分钟前
社区健身系统开发实战:从需求分析到落地部署全流程指南
java·开发语言·小程序·需求分析
覆东流18 分钟前
4.Java运算符与表达式
java·开发语言·后端
JacksonMx26 分钟前
ContentCachingRequestWrapper 实战:解决请求体“只能读一次”的官方方案
java·spring boot·spring
我变成萤火虫27 分钟前
2026 ICPC沈阳邀请赛Vp补题
数据结构·c++·算法·贪心算法·stl·排序算法·动态规划
神威难绷泪28 分钟前
数据结构:二叉树
数据结构·二叉树
风起洛阳@不良使30 分钟前
中级软考(软件攻城狮)第3章知识点——数据结构与数据运算(线性结构+非线性结构)
数据结构·算法·链表
微石科技38 分钟前
医疗设备维保如何从被动维修转向预防管理?宁波微石科技让运行数据提前发信号
java·后端·struts
AndrewHZ44 分钟前
图像处理入门009 | OpenCV 图像读取与显示:imread/imshow 全解析
图像处理·python·opencv·算法·计算机视觉·图像显示
学计算机的计算基1 小时前
TCP 传输层硬核整理:三次握手、四次挥手、拥塞控制一次讲透
java·网络·笔记·网络协议·算法
索西引擎1 小时前
【数据结构】B树与B+树:结构性质、对比分析与磁盘优化机理
数据结构·b树