【Top K 问题】[Leetcode-215] Kth Largest Element in an Array 数组中第K大的数
来源:互联网 发布:跑腿软件哪个好 编辑:程序博客网 时间:2024/05/22 14:07
0. 本文概要
Top K问题在大数据领域非常普遍,而且是在面试中经常被提问的一个问题。
例如: 100w 个数中找出最大的 100 个数。
- 本文概要
- 思路
- 1 堆
- 2 Quick Select
- Kth Largest Element in an Array
- 参考文献
1. 思路
解决Top K问题有两种思路
最直观: 小顶堆(大顶堆 -> 最小100个数);
较高效: Quick Select算法。
下面我们先介绍两种方法, 最后使用Leetcode-215 Kth Largest Element in an Array 进行验证。
1.1 堆
方案 1:在前面的题中,我们已经提到了,用一个含 100 个元素的最小堆完成。复杂度为 O(100w*lg100)。
小顶堆(min-heap)有个重要的性质——每个结点的值均不大于其左右孩子结点的值,则堆顶元素即为整个堆的最小值。
JDK中 PriorityQueue
实现了数据结构堆,通过指定comparator
字段来表示小顶堆
或大顶堆
,默认为null,表示自然序(natural ordering)。
小顶堆解决 Top K
问题的思路:
小顶堆维护当前扫描到的最大100个数,其后每一次的扫描到的元素,若大于堆顶,则入堆,然后删除堆顶;依此往复,直至扫描完所有元素。
Java实现第K大整数代码如下:
public static int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> myQueue = new PriorityQueue<>(k, new Comparator<Integer>(){ public int compare(Integer o1, Integer o2){ return o1 - o2;//小顶堆// return o2 - o1;//大顶堆 } }); for(Integer num: nums){ //如果堆大小小于K, 直接入堆 或者 元素大于小顶堆的堆顶元素,也入堆 if(myQueue.size() < k || num > myQueue.peek() ){ myQueue.offer(num); } if(myQueue.size() > k){ myQueue.poll(); } } return myQueue.peek(); }
1.2. Quick Select
方案 2: 采用快速排序的思想,每次分割之后只考虑比轴大的一部分,知道比轴大的一部分在比 100 多的时候,采用传统排序算法排序,取前 100 个。复杂度为 O(100w*100)。
Quick Select 脱胎于快排(Quick Sort),两个算法的作者都是Hoare,并且思想也非常接近:选取一个基准元素pivot,将数组切分(partition)为两个子数组,比pivot大的扔左子数组,比pivot小的扔右子数组,然后递推地切分子数组。
Quick Select
不同于Quick Sort
的是其没有对每个子数组做切分,而是对目标子数组做切分。
其次,Quick Select
与Quick Sort
一样,是一个不稳定的算法;pivot选取直接影响了算法的好坏,worst case下的时间复杂度达到了O(n^2)
。
下面给出Quick Sort 快速排序
的Java
实现:
感觉我现在都能把快排背下来了。。。。
public static void quickSort(int[] arr, int low, int high){ int pivot; if(low < high){ pivot = partition(arr, low, high); quickSort(arr, pivot+1, high); quickSort(arr, low, pivot-1); } } public static int partition(int[] arr, int low, int high){ int pivotKey = arr[low]; while(low < high){ while(low < high && arr[high] >= pivotKey) high--; swap(arr, low, high); while(low < high && arr[low] <= pivotKey) low++; swap(arr, low, high); } return low; } public static void swap(int[] arr, int low, int high){ int temp = arr[low]; arr[low] = arr[high]; arr[high] = temp; }
Quick Select
的目标是找出第k大元素,所以
- 若切分后的左子数组的长度 > k,则第k大元素必出现在左子数组中;
- 若切分后的左子数组的长度 = k-1,则第k大元素为pivot;
- 若上述两个条件均不满足,则第k大元素必出现在右子数组中。
Quick Select
的Java实现:
public int findKthLargest(int[] nums, int k) { return quickSelect(nums, k, 0, nums.length - 1); } // quick select to find the kth-largest element public int quickSelect(int[] arr, int k, int left, int right) { if (left == right) return arr[right]; //patition方法还是用的 快排中的 partition int index = partition(arr, left, right); if (index - left + 1 > k) return quickSelect(arr, k, left, index - 1); else if (index - left + 1 == k) return arr[index]; else return quickSelect(arr, k - index + left - 1, index + 1, right); }
上面给出的代码都是求解第k大元素;若想要得到Top K元素,仅需要将代码做稍微的修改:比如,扫描完成后的小顶堆对应于Top K,Quick Select算法用中间变量保存Top K元素。
2. Kth Largest Element in an Array
Leetcode 215
import java.util.Comparator;import java.util.PriorityQueue;class Solution { public int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> minQueue = new PriorityQueue<>(k); for (int num : nums) { if (minQueue.size() < k || num > minQueue.peek()) minQueue.offer(num); if (minQueue.size() > k) minQueue.poll(); } return minQueue.peek(); }}
3. 参考文献
James Aspnes, QuickSelect.
- 【Top K 问题】[Leetcode-215] Kth Largest Element in an Array 数组中第K大的数
- Leetcode 215 Kth Largest Element in an Array 数组中第k大的元素
- LeetCode 二分查找第K大的数215. Kth Largest Element in an Array
- Kth Largest Element in an Array 数组中的第K大的数
- 数组-Kth Largest Element in an Array(找出第K大的数)
- [LeetCode] Kth Largest Element in an Array (找出数组的第k大的元素)
- 【LeetCode-面试算法经典-Java实现】【215-Kth Largest Element in an Array(数组中第K大的数)】
- 215. Kth Largest Element in an Array(数组中第k大的数字)
- LeetCode OJ 之 Kth Largest Element in an Array(数组中的第k大元素)
- leetcode 215:Kth Largest Element in an Array ( 分治-求第k小的数,第k大的数)
- Kth Largest Element in an Array(数组中第K大元素)
- 215. Kth Largest Element in an Array(数组中第k大元素)
- 第二周:215. Kth Largest Element in an Array(找出第K大的数)
- 【LeetCode】215. Kth Largest Element in an Array找第K大的元素
- LeetCode 215. Kth Largest Element in an Array(第K大元素)
- leetcode解题之215. Kth Largest Element in an Array java 版(第k大的数字)
- leetcode215---Kth Largest Element in an Array(第k大元素)
- 字符串算法——查找数组第K个最大值( Kth Largest Element in an Array)
- 2017.09.01工作日记
- 线性表的应用1
- 欢迎使用CSDN-markdown编辑器
- CentOS查看和修改PATH环境变量的方法
- Spring09---spring整合JDBC_01_实现增删改查
- 【Top K 问题】[Leetcode-215] Kth Largest Element in an Array 数组中第K大的数
- Atitit 融资 之道 圈钱之道 attilax总结
- The current request is not a multipart request异常
- [PTA MOOC] Maximum Subsequence Sum(25 分)(也是浙大研究生机试的题)
- 再谈服务熔断、服务降级的差异性
- tmux-2.5.tar.gz 下载
- cfA. Odds and Ends
- 如何安装 Composer
- 学后端,一步一坑,遇坑就跳,跳完再爬---之mysql与mysql可视化工具