[数组排序] 0215. 数组中第K个最大元素

文章目录

      • [1. 题目链接](#1. 题目链接)
      • [2. 题目大意](#2. 题目大意)
      • [3. 示例](#3. 示例)
      • [4. 解题思路](#4. 解题思路)
      • [5. 参考代码](#5. 参考代码)

1. 题目链接

215. 数组中的第K个最大元素 - 力扣(LeetCode)


2. 题目大意

描述:给定一个未排序的整数数组 nums 和一个整数 k。

要求:返回数组中第 k 个最大的元素。

说明

  • 要求使用时间复杂度为 O(n) 的算法解决此问题。
  • 1≤k≤nums.length≤105。
  • −104≤nums[i]≤104。

3. 示例

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

4. 解题思路

使用快速排序在每次调整时,都会确定一个元素的最终位置,且以该元素为界限,将数组分成了左右两个子数组,左子数组中的元素都比该元素小,右子数组中的元素都比该元素大。

这样,只要某次划分的元素恰好是第 kk 个下标就找到了答案。并且我们只需关注第 kk 个最大元素所在区间的排序情况,与第 kk 个最大元素无关的区间排序都可以忽略。这样进一步减少了执行步骤。


5. 参考代码

java 复制代码
import java.util.Random;

public class Solution {

    private Random random = new Random();

    // 随机哨兵划分:从 nums[low: high + 1] 中随机挑选一个基准数,并进行移位排序
    private int randomPartition(int[] nums, int low, int high) {
        // 随机挑选一个基准数
        int i = random.nextInt(high - low + 1) + low;
        // 将基准数与最低位互换
        swap(nums, i, low);
        // 以最低位为基准数,然后将数组中比基准数大的元素移动到基准数右侧,比它小的元素移动到基准数左侧。最后将基准数放到正确位置上
        return partition(nums, low, high);
    }

    // 哨兵划分:以第 1 位元素 nums[low] 为基准数,然后将比基准数小的元素移动到基准数左侧,将比基准数大的元素移动到基准数右侧,最后将基准数放到正确位置上
    private int partition(int[] nums, int low, int high) {
        // 以第 1 位元素为基准数
        int pivot = nums[low];

        int i = low, j = high;
        while (i < j) {
            // 从右向左找到第 1 个小于基准数的元素
            while (i < j && nums[j] >= pivot) {
                j--;
            }
            // 从左向右找到第 1 个大于基准数的元素
            while (i < j && nums[i] <= pivot) {
                i++;
            }
            // 交换元素
            swap(nums, i, j);
        }

        // 将基准数放到正确位置上
        swap(nums, j, low);
        return j;
    }

    private void swap(int[] nums, int i, int j) {
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }

    private int quickSort(int[] nums, int low, int high, int k, int size) {
        if (low < high) {
            // 按照基准数的位置,将数组划分为左右两个子数组
            int pivotIndex = randomPartition(nums, low, high);
            if (pivotIndex == size - k) {
                return nums[size - k];
            }
            if (pivotIndex > size - k) {
                return quickSort(nums, low, pivotIndex - 1, k, size);
            }
            if (pivotIndex < size - k) {
                return quickSort(nums, pivotIndex + 1, high, k, size);
            }
        }
        return nums[size - k];
    }

    public int findKthLargest(int[] nums, int k) {
        int size = nums.length;
        return quickSort(nums, 0, nums.length - 1, k, size);
    }
}

相关推荐
liuluyang5301 小时前
C语言C11支持的结构体嵌套的用法
c语言·开发语言·算法·编译·c11
勤劳的进取家2 小时前
贪心算法之最小生成树问题
数据结构·python·算法·贪心算法·排序算法·动态规划
牛奶咖啡.8542 小时前
第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组真题
c语言·数据结构·c++·算法·蓝桥杯
亓才孓3 小时前
[leetcode]stack的基本操作的回顾
算法
小美爱刷题3 小时前
力扣DAY46-50 | 热100 | 二叉树:展开为链表、pre+inorder构建、路径总和、最近公共祖先、最大路径和
算法·leetcode·链表
Fanxt_Ja3 小时前
【数据结构】红黑树超详解 ---一篇通关红黑树原理(含源码解析+动态构建红黑树)
java·数据结构·算法·红黑树
永恒迷星.by3 小时前
全球变暖(蓝桥杯 2018 年第九届省赛)
算法
旧时光林4 小时前
蓝桥杯 分解质因数(唯一分解定理)
数据结构·c++·算法·蓝桥杯·模拟·枚举
烁3474 小时前
每日一题(小白)模拟娱乐篇27
java·数据结构·算法·娱乐
Hello bugyan5 小时前
并查集initial,find,union+应用
数据结构·算法