数组中的第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 ≤ 数组的长度。
解法一:时间O(nlogn),空间O(1)
public class Solution {
public int findKthLargest(int[] nums, int k) {
int len = nums.length;
Arrays.sort(nums);
return nums[len - k];
}
}
解法二:快排
class Solution {
public int findKthLargest(int[] nums, int k) {
int left=0;
int right=nums.length-1;
int target=nums.length-k;
while (true){
int index=partition(nums,left,right);
if (index==target){
return nums[index];
}else if (index>target){
right=index-1;
}else if (index<target){
left=index+1;
}
}
}
private int partition(int[] nums, int i, int j) {
int key=nums[i];
while (i<j){
while (i<j && nums[j]>=key){
j--;
}
if (i<j) nums[i]=nums[j];
while(i<j&&key>=nums[i]){
i++;
}
if (i<j) nums[j]=nums[i];
}
nums[i]=key;
return i;
}
}
解法三:大根堆 时间O(nlogn)
堆
class Solution {
public int findKthLargest(int[] nums, int k) {
int heapLength=nums.length;
buildMaxHeap(nums,heapLength);
for (int i=0;i<k-1;i++){
swap(nums,0,heapLength-1);
heapLength = heapLength-1;
buildMaxHeap(nums,heapLength);
}
return nums[0];
}
private void buildMaxHeap(int[] nums, int heapLength) {
for(int i=(heapLength-1)/2;i>=0;i--){
maxHeapify(i,nums,heapLength);
}
}
private void maxHeapify(int i, int[] nums, int heapLength) {
int l=i*2+1,r=i*2+2,largest=-1;
if (l<heapLength && nums[l]>nums[i]){
largest=l;
}else {
largest=i;
}
if (r<heapLength && nums[r]>nums[largest]){
largest=r;
}
if (i!=largest){
swap(nums,i,largest);
maxHeapify(largest,nums,heapLength); //交换后,largest的子节点可能不满足大根堆的条件
}
}
private void swap(int[] nums, int i, int largest) {
int temp=nums[i];
nums[i]=nums[largest];
nums[largest]=temp;
}
}
解法四:优先队列
优先队列是用堆来实现的
compare()返回值:
- 1:前面的数>后面的数,是降序(从大到小)排列,如果想要改为升序排列,就需要返回1
- -1:前面的数<后面的数,是升序(从小到大)排列,不改变位置就返回-1;
- 0:二者相等,不进行交换,也就不排序。但是要根据题目来判断返回什么。如果数组是无序的,不能直接返回0。若保证升序排列,要返回o1-o2,降序则o2-o1。
- return 0:不交换位置,不排序
- return 1:交换位置
- return -1:不交换位置
- return o1-o2:升序排列
- return o2-o1:降序排列
(a, b) -> a - b 升序
(a, b) -> b - a 降序
public class Solution {
public int findKthLargest(int[] nums, int k) {
int len = nums.length;
// 使用一个含有 len 个元素的最小堆,默认是最小堆,可以不写 lambda 表达式:(a, b) -> a - b 升序
PriorityQueue<Integer> 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();
}
}