LeetCode 精选 TOP 面试题(Java 实现)—— 数组中的第K个最大元素

一、题目描述

1.1 题目
  • 数组中的第K个最大元素

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

  • 示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
  • 示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
  • 说明:
    你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
1.2 知识点
  • 快速选择
  • 快速排序算法
1.3 题目链接

二、解题思路

2.1 自研思路

  这道题我采用的是 快速选择 ,该算法的思路是建立在快速排序算法之上,首先分析题目要求,我们可以发现其实我们并不要数组整体有序,只需保证前 K 个元素有序(包括第 K 个元素),就可以求出数组中的第 K 大元素,因此我们有两种思路:

  • 使用堆排序,维护一个大小为 K 的 大顶堆 ,保证堆顶元素永远是该堆中的第 K 大元素,然后遍历数组并将元素不断插入到该大顶堆即可,当遍历完成后,该大顶推堆顶元素即为所求;

  • 使用选择算法,该算法的核心思想是利用快速排序算法每次确定一个元素的位置,并且可以确定的是该元素的在数组中左侧的元素均小于该元素,该元素在数组中右侧的元素均大于该元素,但需要注意的是当前左右侧元素虽然大小关系确定,但是是无序的。所以我们确定该元素的下标后,判断该下标与我们要寻找的 K 大元素的大小关系,经过判断后就可以将下一轮搜索的范围缩小一半,比如当 nums.length-k(数组从小到大排列,第 k 大元素下标为 nums.length-k)小于当前元素的下标时,则可以确定我们需要找的排序后下标为 nums.length-k 的元素应该位于当前下标的右侧,所以我们缩小搜索范围为 start ~ index-1 ;

2.2 相关知识点

三、实现代码

3.1 自研实现
class Solution {
    public int findKthLargest(int[] nums, int k) {
        return nums[findKthLargest(nums, 0, nums.length-1, nums.length-k)];
    }

    private int findKthLargest(int[] nums, int start, int end, int k) {
        int minPartitionEnd = partition(nums, start, end);
        if(minPartitionEnd == k)
            return minPartitionEnd;
        else if(minPartitionEnd > k)
            return findKthLargest(nums, start, minPartitionEnd-1, k);
        else    
            return findKthLargest(nums, minPartitionEnd+1, end, k);
    }

    private int partition(int[] nums, int start, int end) {
        int target = nums[end], minPartitionEnd = start-1;
        for(int i = start; i < end; i++) 
            if(nums[i] <= target) swap(nums, ++minPartitionEnd, i);
        swap(nums, ++minPartitionEnd, end);
        return minPartitionEnd;
    }

    private void swap(int[] arr, int a, int b){
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}
3.2 示例代码(堆)
class Solution {
    public int findKthLargest(int[] nums, int k) {
        // init heap 'the smallest element first'
        PriorityQueue<Integer> heap =
            new PriorityQueue<Integer>((n1, n2) -> n1 - n2);

        // keep k largest elements in the heap
        for (int n: nums) {
          heap.add(n);
          if (heap.size() > k)
            heap.poll();
        }

        // output
        return heap.poll();        
  }
}
发布了277 篇原创文章 · 获赞 33 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_40697071/article/details/104042765