沧州网站建设的技术方案,wordpress 管网,电商网站开发前景,国外案例网站【问题描述】[中等]
在未排序的数组中找到第 k 个最大的元素。请注意#xff0c;你需要找的是数组排序后的第 k 个最大的元素#xff0c;而不是第 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 个最大的元素。请注意你需要找的是数组排序后的第 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. 暴力解法快排 时间复杂度O(NlogN) 空间复杂度O(1)
import java.util.Arrays;public class Solution {public int findKthLargest(int[] nums, int k) {int len nums.length;Arrays.sort(nums);return nums[len - k];}
}
2. 借助 partition 操作定位到最终排定以后索引为 len - k 的那个元素特别注意随机化切分元素 时间复杂度O(N) 空间复杂度O(1)
public class Solution {public int findKthLargest(int[] nums, int k) {int len nums.length;int left 0;int right len - 1;// 转换一下第 k 大元素的索引是 len - kint 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;}}}/*** 在数组 nums 的子区间 [left, right] 执行 partition 操作返回 nums[left] 排序以后应该在的位置* 在遍历过程中保持循环不变量的语义* 1、[left 1, j] nums[left]* 2、(j, i] nums[left]** param nums* param left* param right* return*/public int partition(int[] nums, int left, int right) {int pivot nums[left];int j left;for (int i left 1; i right; i) {if (nums[i] pivot) {// 小于 pivot 的元素都被交换到前面j;swap(nums, j, i);}}// 在之前遍历的过程中满足 [left 1, j] pivot并且 (j, i] pivotswap(nums, j, left);// 交换以后 [left, j - 1] pivot, nums[j] pivot, [j 1, right] pivotreturn j;}private void swap(int[] nums, int index1, int index2) {int temp nums[index1];nums[index1] nums[index2];nums[index2] temp;}
} import java.util.Random;public class Solution {private static Random random new Random(System.currentTimeMillis());public int findKthLargest(int[] nums, int k) {int len nums.length;int target len - k;int left 0;int right len - 1;while (true) {int index partition(nums, left, right);if (index target) {left index 1;} else if (index target) {right index - 1;} else {return nums[index];}}}// 在区间 [left, right] 这个区间执行 partition 操作private int partition(int[] nums, int left, int right) {// 在区间随机选择一个元素作为标定点if (right left) {int randomIndex left 1 random.nextInt(right - left);swap(nums, left, randomIndex);}int pivot nums[left];int j left;for (int i left 1; i right; i) {if (nums[i] pivot) {j;swap(nums, j, i);}}swap(nums, left, j);return j;}private void swap(int[] nums, int index1, int index2) {int temp nums[index1];nums[index1] nums[index2];nums[index2] temp;}
} import java.util.Random;public class Solution {private static Random random new Random(System.currentTimeMillis());public int findKthLargest(int[] nums, int k) {int len nums.length;int left 0;int right len - 1;// 转换一下第 k 大元素的索引是 len - kint 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;}}}public int partition(int[] nums, int left, int right) {// 在区间随机选择一个元素作为标定点if (right left) {int randomIndex left 1 random.nextInt(right - left);swap(nums, left, randomIndex);}int pivot nums[left];// 将等于 pivot 的元素分散到两边// [left, lt) pivot// (rt, right] pivotint lt left 1;int rt right;while (true) {while (lt rt nums[lt] pivot) {lt;}while (lt rt nums[rt] pivot) {rt--;}if (lt rt) {break;}swap(nums, lt, rt);lt;rt--;}swap(nums, left, rt);return rt;}private void swap(int[] nums, int index1, int index2) {int temp nums[index1];nums[index1] nums[index2];nums[index2] temp;}
}
3. 优先队列 import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len nums.length;// 使用一个含有 len 个元素的最小堆默认是最小堆可以不写 lambda 表达式(a, b) - a - bPriorityQueueInteger 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();}
}
import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len nums.length;// 使用一个含有 len 个元素的最大堆lambda 表达式应写成(a, b) - b - aPriorityQueueInteger maxHeap new PriorityQueue(len, (a, b) - b - a);for (int i 0; i len; i) {maxHeap.add(nums[i]);}for (int i 0; i k - 1; i) {maxHeap.poll();}return maxHeap.peek();}
} import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len nums.length;// 使用一个含有 k 个元素的最小堆PriorityQueueInteger minHeap new PriorityQueue(k, (a, b) - a - b);for (int i 0; i k; i) {minHeap.add(nums[i]);}for (int i k; i len; i) {// 看一眼不拿出因为有可能没有必要替换Integer topEle minHeap.peek();// 只要当前遍历的元素比堆顶元素大堆顶弹出遍历的元素进去if (nums[i] topEle) {minHeap.poll();minHeap.add(nums[i]);}}return minHeap.peek();}
} import java.util.PriorityQueue;public class Solution {public int findKthLargest(int[] nums, int k) {int len nums.length;// 最小堆PriorityQueueInteger priorityQueue new PriorityQueue(k 1, (a, b) - (a - b));for (int i 0; i k; i) {priorityQueue.add(nums[i]);}for (int i k; i len; i) {priorityQueue.add(nums[i]);priorityQueue.poll();}return priorityQueue.peek();}
} import java.util.PriorityQueue;public class Solution {// 根据 k 的不同选最大堆和最小堆目的是让堆中的元素更小// 思路 1k 要是更靠近 0 的话此时 k 是一个较大的数用最大堆// 例如在一个有 6 个元素的数组里找第 5 大的元素// 思路 2k 要是更靠近 len 的话用最小堆// 所以分界点就是 k len - kpublic int findKthLargest(int[] nums, int k) {int len nums.length;if (k len - k) {// System.out.println(使用最小堆);// 特例k 1用容量为 k 的最小堆// 使用一个含有 k 个元素的最小堆PriorityQueueInteger minHeap new PriorityQueue(k, (a, b) - a - b);for (int i 0; i k; i) {minHeap.add(nums[i]);}for (int i k; i len; i) {// 看一眼不拿出因为有可能没有必要替换Integer topEle minHeap.peek();// 只要当前遍历的元素比堆顶元素大堆顶弹出遍历的元素进去if (nums[i] topEle) {minHeap.poll();minHeap.add(nums[i]);}}return minHeap.peek();} else {// System.out.println(使用最大堆);assert k len - k;// 特例k 100用容量为 len - k 1 的最大堆int capacity len - k 1;PriorityQueueInteger maxHeap new PriorityQueue(capacity, (a, b) - b - a);for (int i 0; i capacity; i) {maxHeap.add(nums[i]);}for (int i capacity; i len; i) {// 看一眼不拿出因为有可能没有必要替换Integer topEle maxHeap.peek();// 只要当前遍历的元素比堆顶元素大堆顶弹出遍历的元素进去if (nums[i] topEle) {maxHeap.poll();maxHeap.add(nums[i]);}}return maxHeap.peek();}}
}
【总结】
1.快排核心思想 找partition 随机化可避免极端情况
2.优先队列的使用 最大最小堆
//大堆
PriorityQueueInteger maxHeap new PriorityQueue(capacity, (a, b) - b - a);
//小堆PriorityQueueInteger minHeap new PriorityQueue(k, (a, b) - a - b);3.assert 调试使用 程序或软件正式发布后需要关闭 转载链接https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/partitionfen-er-zhi-zhi-you-xian-dui-lie-java-dai-/
参考链接https://blog.csdn.net/jeikerxiao/article/details/82262487 参考链接https://www.cnblogs.com/wei-jing/p/10806236.html