堆----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;
    }
}
相关推荐
zh_xuan31 分钟前
LeeCode 496. 下一个更大元素I
数据结构·算法·栈·单调栈
机 _ 长40 分钟前
05 智算运维|8 张卡怎么才算「捆成一张」:NCCL 实测与拓扑
运维·人工智能·算法·智算运维
早起CaiCai1 小时前
【2023-01 OM】利用深度学习算法融合异质观测实现海洋场降尺度
人工智能·深度学习·算法
学长毕设2 小时前
基于SpringBoot的野生动物公益保护平台设计与实现-附源码
java·spring boot·后端
梦里寻码2 小时前
我用 NestJS + Vue3 写了一套完整的研发管理系统(58 表 / 229 API / 130 项断言,全开源
前端·后端·算法
SL_staff2 小时前
离散制造排程破局:JVS-APS 四步闭环落地实践(开发者视角)
java·产品·全栈
这个昵称不容易2 小时前
SpringBoot 美容院管理系统:232个Java文件315个接口,5套角色从预约到发货一整条链路
java·springboot·毕设
猿人谷2 小时前
Surrogate Model:让进化算法学会“预测”,为什么它正在成为智能优化的重要技术?
后端·算法·架构
装不满的克莱因瓶3 小时前
【SpringAI Alibaba】ReactAgent记忆管理MessageTrimmingHook与MessageDeletionHook
java·人工智能·ai·ai编程·springai·springaialibaba
文丑颜不良啊3 小时前
LeetCode2241~2260题目解析
java·leetcode