题目描述:
标签:数组 分治 快速选择 排序 堆(优先队列)
给定整数数组
nums
和整数k
,请返回数组中第k
个最大的元素。请注意,你需要找的是数组排序后的第
k
个最大的元素,而不是第k
个不同的元素。
代码:
《一》暴力算法
思路分析:
Arrays.sort()底层用的是快排,时间复杂度是O(NlogN),空间复杂度是O(!)。
注意第K个最大元素对应的下标是nums.length - k
class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length - k];
}
}
《二》快速排序
思路分析:
快排的思想就是选定一个元素,让它左边的元素全部小于它,它右边的元素都大于它,在分别对左右子区间进行递归。其实选定的这个元素在完成一次快排后,就来到了它对应的下标位置。所以在这个题目只需要比较每一快排后对应的下标即可。
import java.util.Random;
class Solution {
private static Random random = new Random(System.currentTimeMillis());
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){
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 privot = nums[left];
int j = left;
for(int i = left + 1;i <= right;i++){
if(nums[i] < privot){
j++;
swap(nums,j,i);
}
}
swap(nums,left,j);
return j;
}
public void swap(int[] nums,int index1,int index2){
int tmp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = tmp;
}
}
《三》堆排序
思路分析:
大顶堆:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;
小顶堆:每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆;
堆排序的思想:将排序数组构成一个大顶堆,此时堆顶的根节点就是最大值,将它与数组最后一个元素交换位置,再对剩下的n-1个数重复这个操作。
//方式一:自己构建大顶堆
class Solution {
public int findKthLargest(int[] nums, int k) {
int heapSize = nums.length;
buildMaxHeap(nums,heapSize);
for(int i = nums.length - 1;i >= nums.length - k + 1;i--){
swap(nums,0,i);
heapSize--;
maxHeapify(nums,0,heapSize);
}
return nums[0];
}
public void buildMaxHeap(int[] nums,int heapSize){
for(int i = heapSize / 2;i >= 0;i--){
maxHeapify(nums,i,heapSize);
}
}
public void maxHeapify(int[] nums,int i,int heapSize){
int left = 2 * i + 1;
int right = 2 * i + 2;
int largest = i;
if(left < heapSize && nums[left] > nums[largest]){
largest = left;
}
if(right < heapSize && nums[right] > nums[largest]){
largest = right;
}
if(largest != i){
swap(nums,i,largest);
maxHeapify(nums,largest,heapSize);
}
}
public void swap(int[] nums,int index1,int index2){
int tmp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = tmp;
}
}
//方式二:利用java提供的API
class Solution {
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> queue = new PriorityQueue<>(); //小顶堆
for(int num : nums){
queue.add(num);
if(queue.size() > k){
queue.poll();
}
}
return queue.peek();
}
}