LeetCode.215-数组中的第K个最大元素
2020-12-20 08:58
标签:部分 渐进 最小堆 mamicode == top 通过 最小 rand 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 TopK问题是一道高频面试题! 由于数组是未排序的,最直接粗暴的方法就是先对数组进行排序,排序后直接通过索引返回满足条件的元素即可。代码简洁到感人。 复杂度:总的时间复杂度就是排序的复杂度:\(O(NlogN)\),没有使用额外的空间,空间复杂度为 \(O(1)\)。 快速排序中,每次partion操作将数组分为两部分,左边小于切分元素,右边大于切分元素。这样我们如果找到这样的一个切分点,partion操作完它右边有 k-1 个元素,那这个切分点就是我们需要的元素。 复杂度:快速排序的复杂度为 \(O(NlogN)\),但是上面的代码仅仅是快速排序的部分实现,其期望时间复杂度为 \(O(N)\),《算法导论》里给出了具体的复杂度分析;空间复杂度为 \(O(logN)\),即递归栈所使用的额外空间。 堆排序有两种思路: 下面是思路一的实现,自己在数组原地实现了最大堆。也可以借助java的PriorityQueue类实现堆。 复杂度:使用思路一原地排序,空间复杂度为 \(O(1)\);时间复杂度为 \(O(NlogN)\),其中构建堆的时间复杂度为 \(O(N)\),删除k个元素的时间代价为 \(O(klogN)\),渐进时间复杂度为 \(O(NlogN)\)。使用思路二的最小堆,时间复杂度为 \(O(Nlog(k))\),如果不使用递归不考虑递归栈的空间,空间复杂度为 \(O(k)\)。 !!!解法二快速排序和解法三堆排序是TopK问题推荐的解法,一定要掌握! LeetCode.215-数组中的第K个最大元素 标签:部分 渐进 最小堆 mamicode == top 通过 最小 rand 原文地址:https://www.cnblogs.com/rezero/p/13222211.html题目
示例
??输入:[3,2,3,1,2,4,5,5,6] 和 k = 4
??输出:4解法一:排序+查找
class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
}
解法二:快速排序(单边)
class Solution {
Random rand = new Random();
public int findKthLargest(int[] nums, int k) {
return findK(nums, 0, nums.length - 1, k);
}
private int findK(int[] nums, int lo, int hi, int k){
int j = partion(nums, lo, hi);
if(j == k -1) return nums[j];
else if(j > k - 1){
return findK(nums, lo, j - 1, k);
}
else{
return findK(nums, j + 1, hi, k);
}
}
private int partion(int[] nums, int lo, int hi){
int r = rand.nextInt(hi - lo + 1) + lo; // 切分点的位置,随机选择很关键
int tmp = nums[r]; // 哨兵
nums[r] = nums[lo];
nums[lo] = tmp;
while(lo = tmp){
lo++;
}
nums[hi] = nums[lo];
}
nums[lo] = tmp;
return lo;
}
}
注意:选择切分点对于极端情况下程序的计算时间影响很大。如下图,对于leetcode给的测试样例,不使用随机操作程序执行时间会增加5倍以上。解法三:堆排序
class Solution {
public int findKthLargest(int[] nums, int k) {
int heapSize = nums.length;
for(int i = heapSize/2; i >= 0; i--){
adjust(nums, i, heapSize); // 通过调整使得初始堆有序
}
while(--heapSize > nums.length - k){
swap(nums, 0, heapSize);
adjust(nums, 0, heapSize);
}
return nums[heapSize + 1];
}
private void adjust(int[] nums, int i, int size){
while(2 * i + 1 arr[j]) break;
swap(nums, i, j);
i = j;
}
}
private void swap(int[] nums, int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
上一篇:JAVA并行程序基础1
下一篇:java 日期
文章标题:LeetCode.215-数组中的第K个最大元素
文章链接:http://soscw.com/index.php/essay/37389.html