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

题目:

215. 数组中的第K个最大元素
在这里插入图片描述

题解:

1. 题解一:暴力解法(先排序再查找)

在这里插入图片描述
在这里插入图片描述

2. 题解二:使用最小堆(采用优先队列实现)

在这里插入图片描述
在这里插入图片描述

3. 题解三:快速选择算法(基于快速排序的选择方法)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码:

1. 代码一:暴力解法(先排序再查找)

// 方法1:暴力解法
public static int findKthLargest(int[] nums, int k) {
    int len = nums.length;
    Arrays.sort(nums);
    return nums[len - k];
}

2. 代码二:使用最小堆(采用优先队列实现)

// 方法2:使用最小堆(采用优先队列实现)
public static int findKthLargest(int[] nums, int k) {
    // 默认小顶堆,优先级队列,默认按小顶堆,移除最小的
    // 优先队列实现最小堆: PriorityQueue<Integer> queue = new PriorityQueue<>((n1, n2) -> n1 - n2);
    // 优先队列实现最大堆: PriorityQueue<Integer> queue = new PriorityQueue<>((n1, n2) -> n2 - n1);
    PriorityQueue<Integer> queue = new PriorityQueue<>();
    // keep k largest elements in the heap
    // 堆里总保存着k个元素,这个k个就是从第一大到第k大,堆自动调整大小
    for(int i = 0; i < nums.length; i++)
    {
        queue.offer(nums[i]);
        // 维护堆的大小为 k
        if(queue.size() > k)
        {
            // 弹出最顶端的数,并删除
            queue.poll();
        }
    }
    // 取最顶端的数
    return queue.peek();
}

3. 代码三:快速选择算法(基于快速排序的选择方法)

import java.util.*;

public class code215 {

    // 方法3:快速选择算法(基于快速排序的选择方法)    
    public static int findKthLargest(int[] nums, int k) {
        return quickSelect(nums, 0, nums.length - 1, nums.length - k);
    }

    public static int quickSelect(int[] a, int l, int r, int index) {
        int q = randomPartition(a, l, r); // 在分解的过程当中,我们会对子数组进行随机化划分
        if (q == index) { // 如果划分得到的 q 正好就是我们需要的下标,就直接返回 a[q];
            return a[q];
        } else { // 否则,如果 q 比目标下标小,就递归右子区间,否则递归左子区间。
            return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
        }
    }

    // 随机化划分元素
    public static int randomPartition(int[] a, int l, int r) {
        // 在区间 [l, r] 随机选择一个元素作为标定点
        Random random = new Random();
        int i = random.nextInt(r - l + 1) + l; // 获取随机点 i
        swap(a, i, r); // 将随机点 i 作为右端点
        return partition(a, l, r);
    }

    // 在区间 [left, right] 这个区间执行 partition(划分)操作
    public static int partition(int a[], int left, int right)
    {
        // 选取中轴元素
        int pivot = a[left];
        int i = left + 1;
        int j = right;
        while(true)
        {
            // 向右找到第一个大于 pivot 的元素位置
            while(i <= j && a[i] <= pivot)
            {
                i++;
            }
            // 向左找到第一个小于 pivot 的元素位置
            while(i <= j && a[j] >= pivot)
            {
                j--;
            }
            if(i >= j)
            {
                break;
            }
            // 交换两个元素的位置,使得左边的元素不大于pivot,右边的不小于pivot
            int temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
        a[left] = a[j];
        // 使中轴元素处于有序的位置
        a[j] = pivot;
        return j;
    }

    // 交换两个元素
    public static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

    public static void main(String[] args) {
        int nums1[] = { 3, 2, 1, 5, 6, 4 };
        int k1 = 2;
        int res1 = findKthLargest(nums1, k1);
        System.out.println(res1);

        int nums2[] = { 3, 2, 3, 1, 2, 4, 5, 5, 6 };
        int k2 = 4;
        int res2 = findKthLargest(nums2, k2);
        System.out.println(res2);
    }
}

参考:

  1. 数组中的第K个最大元素
  2. 通过 partition 减治 + 优先队列(Java、C++、Python)
  3. java代码的3种答案
  4. JavaScript:四种方式解Topk问题
  5. 【数组中的第K个最大元素】堆的使用和实现
  6. 数组中的第K个最大元素 c++实现三种解法 暴力法、使用小顶堆和选择算法 图示讲解
©️2020 CSDN 皮肤主题: 撸撸猫 设计师: 设计师小姐姐 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值