算法47,分治快排,第K大

1. 代码逻辑解析

  • 随机选基准值 :nums[new Random().nextInt(r-l+1)+l] 随机选取基准值 key,避免有序数组下的最坏情况。
  • 三路分区 :将当前区间 [l, r] 划分为三部分:小于 key、等于 key、大于 key。
    • left 指向大于 key 区域的末尾,right 指向小于 key 区域的开头。
    • 遍历数组,将元素交换到对应区域。
  • 分类讨论 :
    • b 为大于 key 的元素个数,c 为等于 key 的元素个数。
    • 若 c >= k(第 k 大元素在等于 key 的区域),直接返回 key。
    • 若 b >= k(第 k 大元素在大于 key 的区域),递归左半部分(大于 key 的区域)。
    • 否则(第 k 大元素在小于 key 的区域),递归右半部分,并更新 k = k - b - c。

2. 复杂度分析

  • 时间复杂度 :平均 O(n),最坏情况(每次分区极不均匀)为 O(n²)。随机化基准值可有效避免最坏情况。
  • 空间复杂度 :O(log n)(递归栈深度,随机化下平均对数级)。

3. 优缺点评价

  • 优点:利用了三路快排处理重复元素的优势,逻辑严谨,效率较高。
  • 缺点 :
    • 每次递归都 new Random(),有一定性能开销。
    • 分区逻辑变量较多(如 left-1、right+1),容易在边界条件上出错。

4. 优化与替代方案

  • 优化建议 :
    • 将 Random 实例提取为全局静态变量,避免频繁创建。
    • 当区间较小时(如长度 < 10),可切换为插入排序以提升缓存命中率。
  • 替代方案 :
    • 最小堆 :维护一个大小为 k 的最小堆,时间复杂度 O(n log k),空间复杂度 O(k),适合处理海量数据。
    • 快速选择(双路分区):常规的双指针分区同样可以实现 O(n) 的平均时间复杂度。

5. 注意事项

  • 题目明确"第 k 个最大元素"允许重复(如示例 2),三路快排恰好适合此场景。
  • 递归终止条件 if(l==r) return nums[l]; 确保了区间缩小到单个元素时正确返回。
相关推荐
考虑考虑3 小时前
JDK26中的List.ofLazy()
java·后端·java ee
小蒜学长3 小时前
基于SpringBoot的公寓报修管理系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·公寓报修管理系统·多角色协同
for_ever_love__4 小时前
MySQL 主从复制讲透:binlog 原理、搭建步骤与读写分离
java·数据库·mysql·binlog·读写分离·原理·主从复制
小π军6 小时前
操作系统面试题
java·linux·服务器
倔强的石头1066 小时前
应用账号最小权限实践:读写账号、报表账号、运维账号分层
java·运维·开发语言
Shaoshing7 小时前
ThreadLocal
java·jvm·threadlocal
写后端的胖头鱼7 小时前
一文详解CAS
java·jvm·spring·cas·乐观锁·自旋
鱼宵7 小时前
Spring AI 提示词模板:{变量} 参数化 + few-shot,一条提示词反复用
java·人工智能·spring·few-shot·提示词工程·springai
蜗牛互联网7 小时前
Python消费Responses SSE事件:增量文本、超时与取消
java·开发语言·人工智能·后端·python