题目:
题解:
1. 题解一:暴力解法(先排序再查找)
2. 题解二:使用最小堆(采用优先队列实现)
3. 题解三:快速选择算法(基于快速排序的选择方法)
代码:
1. 代码一:暴力解法(先排序再查找)
// 方法1:暴力解法
public static int findKthLargest(int[] nums, int k) {
int len = nums.length;
Arrays.sort(nums);
return nums[len - k];
}
2. 代码二:使用最小堆(采用优先队列实现)
// 方法2:使用最小堆(采用优先队列实现)
public static int findKthLargest(int[] nums, int k) {
// 默认小顶堆,优先级队列,默认按小顶堆,移除最小的
// 优先队列实现最小堆: PriorityQueue<Integer> queue = new PriorityQueue<>((n1, n2) -> n1 - n2);
// 优先队列实现最大堆: PriorityQueue<Integer> queue = new PriorityQueue<>((n1, n2) -> n2 - n1);
PriorityQueue<Integer> queue = new PriorityQueue<>();
// keep k largest elements in the heap
// 堆里总保存着k个元素,这个k个就是从第一大到第k大,堆自动调整大小
for(int i = 0; i < nums.length; i++)
{
queue.offer(nums[i]);
// 维护堆的大小为 k
if(queue.size() > k)
{
// 弹出最顶端的数,并删除
queue.poll();
}
}
// 取最顶端的数
return queue.peek();
}
3. 代码三:快速选择算法(基于快速排序的选择方法)
import java.util.*;
public class code215 {
// 方法3:快速选择算法(基于快速排序的选择方法)
public static int findKthLargest(int[] nums, int k) {
return quickSelect(nums, 0, nums.length - 1, nums.length - k);
}
public static int quickSelect(int[] a, int l, int r, int index) {
int q = randomPartition(a, l, r); // 在分解的过程当中,我们会对子数组进行随机化划分
if (q == index) { // 如果划分得到的 q 正好就是我们需要的下标,就直接返回 a[q];
return a[q];
} else { // 否则,如果 q 比目标下标小,就递归右子区间,否则递归左子区间。
return q < index ? quickSelect(a, q + 1, r, index) : quickSelect(a, l, q - 1, index);
}
}
// 随机化划分元素
public static int randomPartition(int[] a, int l, int r) {
// 在区间 [l, r] 随机选择一个元素作为标定点
Random random = new Random();
int i = random.nextInt(r - l + 1) + l; // 获取随机点 i
swap(a, i, r); // 将随机点 i 作为右端点
return partition(a, l, r);
}
// 在区间 [left, right] 这个区间执行 partition(划分)操作
public static int partition(int a[], int left, int right)
{
// 选取中轴元素
int pivot = a[left];
int i = left + 1;
int j = right;
while(true)
{
// 向右找到第一个大于 pivot 的元素位置
while(i <= j && a[i] <= pivot)
{
i++;
}
// 向左找到第一个小于 pivot 的元素位置
while(i <= j && a[j] >= pivot)
{
j--;
}
if(i >= j)
{
break;
}
// 交换两个元素的位置,使得左边的元素不大于pivot,右边的不小于pivot
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
a[left] = a[j];
// 使中轴元素处于有序的位置
a[j] = pivot;
return j;
}
// 交换两个元素
public static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
public static void main(String[] args) {
int nums1[] = { 3, 2, 1, 5, 6, 4 };
int k1 = 2;
int res1 = findKthLargest(nums1, k1);
System.out.println(res1);
int nums2[] = { 3, 2, 3, 1, 2, 4, 5, 5, 6 };
int k2 = 4;
int res2 = findKthLargest(nums2, k2);
System.out.println(res2);
}
}