题目
给定一个数组,求数组中第k大的数
- 利用快排思想,因为快拍选中的哨兵元素位置是最终排序后的数组中确定的,所以只需要每次查找哨兵元素的位置是否匹配即可,将数组按照降序排列,当哨兵元素索引大于k,说明要去右半区递归,负责去左半区,相等返回答案
function quickSelect(arr, left, right, k) {
if (left === right) {
return arr[left];
}
// 随机查找哨兵元素索引
let pivotIndex = Math.floor(Math.random() * (right - left + 1)) + left;
// 分左右
pivotIndex = partition(arr, left, right, pivotIndex);
if (k === pivotIndex) {
return arr[k];
} else if (k < pivotIndex) {
// 去左半区
return quickSelect(arr, left, pivotIndex - 1, k);
} else {
// 去右半区
return quickSelect(arr, pivotIndex + 1, right, k);
}
}
function partition(arr, left, right, pivotIndex) {
let pivot = arr[pivotIndex];
[arr[pivotIndex], arr[right]] = [arr[right], arr[pivotIndex]];
// 将数组降序,所以左边是大于哨兵元素的区间
let storeIndex = left;
for (let i = left; i < right; i++) {
if (arr[i] > pivot) {
[arr[storeIndex], arr[i]] = [arr[i], arr[storeIndex]];
storeIndex++;
}
}
// 排序完成放置哨兵元素到正确位置
[arr[right], arr[storeIndex]] = [arr[storeIndex], arr[right]];
return storeIndex;
}
function findKthLargest(nums, k) {
return quickSelect(nums, 0, nums.length - 1, k - 1);
}
// 示例
let nums = [3, 2, 1, 5, 6, 4];
let k = 2;
console.log(findKthLargest(nums, k)); // 输出:5