Leetcode——数组中的第K个最大元素

Posted Yawn,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——数组中的第K个最大元素相关的知识,希望对你有一定的参考价值。

1. 题目

2. 题解

(1)直接排序

public class Solution {
    public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        Arrays.sort(nums);
        return nums[len - k];
    }
}

(2)利用快排(直接快排还超级超级慢)

class Solution {
    public int findKthLargest(int[] nums, int k) {
        quickSort(nums, 0, nums.length - 1);
        int count = 0;
        for(int i = nums.length - 1; i >=0; i--){
            count++;
            if(count == k)
                return nums[i];
        }
        return 0;
    }

    private void quickSort(int[] arr, int left, int right) {
        // 子数组长度为 1 时终止递归
        if (left >= right) return;
        // 哨兵划分操作(以 arr[l] 作为基准数)
        int i = left, j = right;
        while (i < j) {
            while (i < j && arr[j] >= arr[left]) j--;
            while (i < j && arr[i] <= arr[left]) i++;
            swap(arr, i, j);
        }
        swap(arr, i, left);
        // 递归左(右)子数组执行哨兵划分
        quickSort(arr, left, i - 1);
        quickSort(arr, i + 1, right);
    }

    private void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
}

(3)快排(改善)

  • 由此可以发现每次经过「划分」操作后,我们一定可以确定一个元素的最终位置,即 x 的最终位置为。
  • 所以只要某次划分的 q 为倒数第 k 个下标的时候,我们就已经找到了答案。
public class Solution {

    public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;

        // 转换一下,第 k 大元素的索引是 len - k
        int target = len - k;

        while (true) {
            int index = partition(nums, left, right);
            if (index == target) {
                return nums[index];
            } else if (index < target) {
                left = index + 1;
            } else {
                right = index - 1;
            }
        }
    }

    /**
     由此可以发现每次经过「划分」操作后,我们一定可以确定一个元素的最终位置,即 x 的最终位置为。
     所以只要某次划分的 q 为倒数第 k 个下标的时候,我们就已经找到了答案。
     */
    public int partition(int[] arr, int left, int right) {
        // 哨兵划分操作, left为哨兵
        int i = left, j = right;
        while (i < j) {
            while (i < j && arr[j] >= arr[left]) j--;
            while (i < j && arr[i] <= arr[left]) i++;
            swap(arr, i, j);
        }
        swap(arr, i, left);
        // 递归左(右)子数组执行哨兵划分
        return i;
    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

(4)优先队列

优先队列的思路是很朴素的。因为第 K 大元素,其实就是整个数组排序以后后半部分最小的那个元素。因此,我们可以维护一个有 K 个元素的最小堆:

1、如果当前堆不满,直接添加;

2、堆满的时候,如果新读到的数小于等于堆顶,肯定不是我们要找的元素,只有新都到的数大于堆顶的时候,才将堆顶拿出,然后放入新读到的数,进而让堆自己去调整内部结构。

public class Solution {

    public int findKthLargest(int[] nums, int k) {
        int len = nums.length;
        // 使用一个含有 len 个元素的最小堆,默认是最小堆,可以不写 lambda 表达式:(a, b) -> a - b
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(len, (a, b) -> a - b);
        for (int i = 0; i < len; i++) {
            minHeap.add(nums[i]);
        }
        for (int i = 0; i < len - k; i++) {
            minHeap.poll();
        }
        return minHeap.peek();
    }
}

以上是关于Leetcode——数组中的第K个最大元素的主要内容,如果未能解决你的问题,请参考以下文章

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

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

[leetcode]215. 数组中的第K个最大元素

LeetCode215. 数组中的第K个最大元素

#yyds干货盘点# LeetCode 腾讯精选练习 50 题:数组中的第K个最大元素

《LeetCode之每日一题》:97.数组中的第K个最大元素