LeetCode:215. 数组中的第K个最大元素
思路:
- 基于快排的选择方法
- 小顶堆
AC Code 基于快排的选择方法
class Solution {
// 随机数
Random random = new Random();
public int findKthLargest(int[] nums, int k) {
// 第 k 大
int left = 0, right = nums.length - 1, kindex = nums.length - k;
int ans = quickSelect(nums, left, right, kindex);
return ans;
}
// 基于快排的选择算法
public int quickSelect(int[] arr, int left, int right, int kindex) {
int idx = randomPartition(arr, left, right);
if(idx == kindex) return arr[idx];
// else
// 偏左 >> 往右区间靠
// 递归
return idx > kindex ? quickSelect(arr, left, idx - 1, kindex)
: quickSelect(arr, idx + 1, right, kindex);
}
// 随机数分区
public int randomPartition(int[] arr, int left, int right){
// 随机数 > [left, right]
int q = random.nextInt(right - left + 1) + left;
// 交换位置
swap(arr, q, right);
int index = partition(arr, left, right);
return index;
}
// 分区
public int partition(int[] arr, int left, int right){
// x 就是选到的随机数
int x = arr[right], i = left;
// 左右分
for(int j = left; j < right; j++) {
// mark: lan
if(arr[j] <= x) {
// 放到区间左边
swap(arr, i++, j);
}
}
// 例子: for 循环后最终效果应该是 [2, 3, 1, 4, | 9, 6, 8, 7, x = 5]
// 将 5 换回去中间
swap(arr, i, right);
return i;
}
// 交换
public void swap(int[] arr, int x, int y){
int tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
// 这里不能用 ^ 来进行交换 >>
// 因为分区的时候(mark:lan),会有 x == y 的情况, 这时候会将 arr 中的元素变成 0
}
}
时间复杂度: O ( N ) O(N) O(N)
AC Code 优先队列构建小顶堆
class Solution {
public int findKthLargest(int[] nums, int k) {
// topK 问题
PriorityQueue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>(){
public int compare(Integer a, Integer b) {
return b - a;
}
});
int len = nums.length;
for(int i = 0; i < len; i++) {
queue.add(nums[i]);
}
for(int i = 1; i < k; i++) {
queue.poll();
}
return queue.peek();
}
}