LeetCode Hot100 215. 数组中的第K个最大元素

题目

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

复制代码
输入: [3,2,1,5,6,4], k = 2
输出: 5

示例 2:

复制代码
输入: [3,2,3,1,2,4,5,5,6], k = 4
输出: 4

提示:

  • 1 <= k <= nums.length <= 105
  • -104 <= nums[i] <= 104

代码&注释

java 复制代码
class Solution {
    /**
     * 查找数组中第 k 个最大的元素(即第 k 大)
     * 
     * 思路:先对整个数组进行升序排序,然后第 k 大就是倒数第 k 个元素,
     *       即索引为 nums.length - k 的元素。
     * 
     * 注意:此方法时间复杂度为 O(n log n),不是最优解(最优可用快速选择,平均 O(n)),
     *       但逻辑简单、易于理解。
     * 
     * @param nums 输入数组
     * @param k 第 k 大(k 从 1 开始计数)
     * @return 第 k 个最大的元素;若输入非法,返回 0
     */
    public int findKthLargest(int[] nums, int k) {
        // 边界检查:数组为空、长度为 0 或 k 超出范围
        if (nums == null || nums.length == 0 || k > nums.length) {
            return 0;
        }
        
        // 对整个数组进行升序快速排序
        quick_sort(nums, 0, nums.length - 1);
        
        // 排序后,第 k 大的元素位于倒数第 k 个位置
        // 例如:[1,2,3,4,5],第 2 大是 4,索引 = 5 - 2 = 3
        return nums[nums.length - k];
    }

    /**
     * 快速排序(递归实现,原地排序)
     * 
     * 采用"三路划分"思想的简化版(实际是标准双指针分区)
     * 目标:将数组 [l, r] 区间按升序排列
     * 
     * @param nums 待排序数组
     * @param l 左边界(包含)
     * @param r 右边界(包含)
     */
    public void quick_sort(int[] nums, int l, int r) {
        // 递归终止条件:区间无效(只有一个元素或空)
        if (l >= r) {
            return;
        }

        // 初始化左右指针
        int i = l; // 左指针,从左向右扫描
        int j = r; // 右指针,从右向左扫描

        // 选择基准值(pivot):取中间位置的元素,避免最坏情况(如已排序数组)
        // 使用 l + (r - l) / 2 防止整数溢出(等价于 (l + r) / 2,但更安全)
        int pivot = nums[l + (r - l) / 2];

        // 分区过程:将小于 pivot 的放左边,大于 pivot 的放右边
        while (i <= j) {
            // 从左边找到第一个 >= pivot 的元素
            while (nums[i] < pivot) {
                i++;
            }
            // 从右边找到第一个 <= pivot 的元素
            while (nums[j] > pivot) {
                j--;
            }
            
            // 如果两个指针未交错,说明找到了一对需要交换的元素
            if (i <= j) {
                // 交换 nums[i] 和 nums[j]
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
                
                // 移动指针,继续扫描
                i++;
                j--;
            }
        }

        // 递归处理左右两个子区间
        // 注意:此时 j 是左半部分的右边界,i 是右半部分的左边界
        if (l < j) {
            quick_sort(nums, l, j);   // 排序左半部分 [l, j]
        }
        if (i < r) {
            quick_sort(nums, i, r);   // 排序右半部分 [i, r]
        }
    }
}
相关推荐
仰泳的熊猫1 小时前
题目2570:蓝桥杯2020年第十一届省赛真题-成绩分析
数据结构·c++·算法·蓝桥杯
无极低码4 小时前
ecGlypher新手安装分步指南(标准化流程)
人工智能·算法·自然语言处理·大模型·rag
软件算法开发5 小时前
基于海象优化算法的LSTM网络模型(WOA-LSTM)的一维时间序列预测matlab仿真
算法·matlab·lstm·一维时间序列预测·woa-lstm·海象优化
罗超驿5 小时前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist
superior tigre5 小时前
22 括号生成
算法·深度优先
努力也学不会java6 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试
旖-旎7 小时前
二分查找(x的平方根)(4)
c++·算法·二分查找·力扣·双指针
ECT-OS-JiuHuaShan7 小时前
朱梁万有递归元定理,重构《易经》
算法·重构
智者知已应修善业8 小时前
【51单片机独立按键控制数码管移动反向,2片74CH573/74CH273段和位,按键按下保持原状态】2023-3-25
经验分享·笔记·单片机·嵌入式硬件·算法·51单片机