当前位置: 首页 > news >正文

堆----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的元素

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

                细节注意:

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

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

 */

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

http://www.dtcms.com/a/311996.html

相关文章:

  • [buuctf-misc]喵喵喵
  • Linux学习--数据结构
  • 前端-移动Web-day3
  • 基于springboot的郑州旅游景点推荐系统
  • Kotlin单例模式懒汉模式:LazyThreadSafetyMode.SYNCHRONIZED(2)
  • 多线程(二) ~ 线程核心属性与状态
  • C#中对于List的多种排序方式
  • LeeCode 88. 合并两个有序数组
  • DeepSpeed - 超大LLM分布式训练框架 ZeRO技术
  • Python day32
  • 力扣 二叉树遍历 中序/前序/后序(递归和迭代版)
  • dbt中多源数据的处理
  • 混合嵌入与置信度增强:新一代RAG技术如何提升LLM性能
  • 1.6 vue 监听
  • JavaScript 原始值与引用值
  • SQL语言学习(group by,having)
  • PyTorch 中 Tensor 统计学函数及相关概念
  • 基于单片机一氧化碳CO检测/煤气防中毒检测报警系统
  • OneCode 3.0智能分页拦截器深度解析:从拦截机制到性能优化
  • 轨道追逃博弈仿真
  • 输电线路建模与电力负荷特性详解(含等值模型与曲线分析)
  • Vue 详情模块 4
  • SQL语言学习(JOIN)
  • Orange的运维学习日记--25.Linux文件系统基本管理
  • 使用xshell连接远程腾讯云服务器,报错:Xshell Socket error Event: 32 Error: 10053
  • 智能图书馆管理系统开发实战系列(五):前后端集成 - koffi调用与接口设计
  • 用resmon搜索某文件被未知程序占用而无法删除
  • 第15届蓝桥杯Python青少组_省赛_中/高级组2024年8月真题
  • Java,八股,cv,算法——双非研0四修之路day23
  • SpringBoot 信用卡检测、OpenAI gym、OCR结合、DICOM图形处理、知识图谱、农业害虫识别实战