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

7.3 分治-快排:LeetCode 215.数组中的第K个最大元素

1. 题目链接

LeetCode 215. 数组中的第K个最大元素
题目要求:给定整数数组 nums 和整数 k,返回数组中第 k 大的元素。例如,数组 [3,2,1,5,6,4] 中第2大的元素是5。


2. 题目描述
  • 输入:整数数组 nums 和整数 k,例如 nums = [3,2,1,5,6,4], k = 2
  • 输出:第 k 大的元素,例如 5
  • 要求:时间复杂度尽量低,且不允许使用内置排序函数。

3. 示例分析

示例 1
输入:nums = [3,2,1,5,6,4], k = 2
输出:5
分析
排序后的数组为 [1,2,3,4,5,6],倒数第2个元素是5。

示例 2
输入:nums = [2,2,3,1], k = 2
输出:2
分析
排序后数组为 [1,2,2,3],倒数第2个元素是2。
若使用三路快速排序,重复元素会被集中处理,减少递归次数。


4. 算法思路
核心思想:随机化三路快速排序
  1. 三路划分:将数组分为三部分:< key== key> key
    • 优点:避免重复元素的重复比较,提升效率。
  2. 随机选择基准值:随机选取 key 防止最坏时间复杂度退化。
  3. 分治策略:递归处理左右子数组,中间部分(== key)无需处理。
求解第K大的元素
  1. 排序:对数组进行升序排序。
  2. 直接访问:第 k 大的元素位于排序后的 nums[nums.size() - k]

5. 边界条件与注意事项
  1. 输入合法性
    • 数组非空,且 1 ≤ k ≤ nums.size()(题目保证)。
  2. 随机化基准值
    • 使用 srand(time(NULL)) 初始化随机种子,避免固定划分导致性能下降。
  3. 三路划分终止条件
    • 递归终止条件 if (a >= b) return; 确保子数组长度为1时停止。
  4. 时间复杂度
    • 平均 O(n log n),最坏 O(n²)(概率极低)。
  5. 空间复杂度
    • 递归栈深度平均 O(log n),最坏 O(n)

6. 代码实现与逐行解析
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        srand(time(NULL));       // 初始化随机种子
        qsort(nums, 0, nums.size() - 1);  // 三路快速排序
        return nums[nums.size() - k];     // 直接访问第k大元素
    }

    void qsort(vector<int>& nums, int a, int b) {
        if (a >= b) return;      // 终止条件:子数组长度为0或1

        int key = getRandomValue(nums, a, b); // 随机选择基准值

        // 三路划分:初始化指针
        int i = a, left = a - 1, right = b + 1;
        while (i < right) {
            if (nums[i] < key) {
                swap(nums[++left], nums[i++]); // 小于key,交换到左区
            } else if (nums[i] == key) {
                i++;                          // 等于key,跳过
            } else {
                swap(nums[--right], nums[i]); // 大于key,交换到右区
            }
        }

        // 递归处理左右子数组
        qsort(nums, a, left);    // 左区:[a, left]
        qsort(nums, right, b);    // 右区:[right, b]
    }

    int getRandomValue(vector<int>& nums, int a, int b) {
        int r = rand();                     // 生成随机数
        return nums[a + r % (b - a + 1)];    // 返回区间[a, b]内的随机元素
    }
};

在这里插入图片描述

代码解析
  1. 主函数 findKthLargest
    • 初始化随机种子,调用 qsort 排序数组,返回第 k 大元素。
  2. 三路快速排序 qsort
    • 随机基准值:通过 getRandomValue[a, b] 随机选取元素,避免固定选首元素导致最坏情况。
    • 三路划分
      • left 指向小于 key 的右边界,right 指向大于 key 的左边界。
      • 循环结束后,区间划分为:[a, left] < key(left, right) == key[right, b] > key
    • 递归处理:仅对左右子数组递归排序,中间部分已有序。
  3. 随机函数 getRandomValue
    • 生成 [a, b] 内的随机索引,确保基准值选取的随机性。

总结

通过三路快速排序结合随机化基准值,能够高效处理重复元素,平均时间复杂度为 O(n log n)。虽然题目可以进一步优化为快速选择算法(平均 O(n)),但本实现通过完整排序直观解决问题,且代码简洁易懂。三路划分在处理大量重复数据时优势明显,是快速排序的重要优化方向。

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

相关文章:

  • CompletableFuture 与反应式编程:异步编程的两种范式对比与实战
  • 简化Rust开发:探索lombok-macros crate
  • 01-性能测试
  • 【NLP 52、多模态相关知识】
  • Redis的Lua脚本
  • Docker 安装 Elasticsearch 教程
  • 人工智能之数学基础:基于吉文斯变换完成矩阵的QR分解
  • leetcode-热题100(3)
  • 【Triton 教程】triton_language.arange
  • 【C++】vector的模拟实现
  • 【AI插件开发】Notepad++ AI插件开发实践(代码篇):从Dock窗口集成到功能菜单实现
  • C++动态库对外接口通过接口方式实现
  • 二维码扫不出?用QR Research工具
  • LangChain接入azureopenai步骤(2025年初)
  • ctfshow
  • Android 10.0 通过广播控制systemui状态栏动态显示和隐藏功能实现
  • docker的文件系统Overlay2
  • 【自学笔记】jQuery语言基础知识点总览-持续更新
  • 《UNIX网络编程卷1:套接字联网API》第5章 TCP客户服务器程序示例
  • 洛谷题单3-P1980 [NOIP 2013 普及组] 计数问题-python-流程图重构
  • 【力扣hot100题】(034)LRU缓存
  • 红帽Linux怎么重置密码
  • 【测试】每日3道面试题 4/1,4/2
  • 架构设计基础系列:事件溯源模式浅析
  • bit与byte的区别与联系?
  • TCP断开连接
  • Amodal3R ,南洋理工推出的 3D 生成模型
  • LXC image download
  • JS—图片格式:1分钟掌握图片选择
  • 多线程代码案例 - 1