题目
给定一组无序数组,求其中第k小的数
- 利用快排的分治思想,每次等于区间的位置是固定的,只需要查找每次分治时等于区间的索引是否有 k ,没有则根据 k 是在小于区间还是大于区间,往一个方向进行递归
let arr = [3, 5, 6, 7, 8, 3, 4, 5];
//划分小于、等于、大于区间
function cutting(arr, num, pleft, pright, k) {
let left = pleft - 1;
let right = pright + 1;
for (let i = pleft; i < pright + 1; i++) {
if (i == right) {
break;
}
if (arr[i] < num) {
[arr[left + 1], arr[i]] = [arr[i], arr[left + 1]];
left++;
} else if (arr[i] == num) {
continue;
} else {
[arr[i], arr[right - 1]] = [arr[right - 1], arr[i]];
right--;
//使得下轮比较从右边交换过来的数
i--;
}
}
// 找到第 k 小的数
if (left < k < right) {
return [left, right, arr[left + 1]];
} else {
//返回小于、大于区间的右、左边界
return [left, right, k <= left ? true : false];
}
}
function sort(arr, left, right, k) {
if (left >= right) {
return;
}
//取区间随机值和最后一个数交换
let rand = left + parseInt(Math.random() * (right - left + 1));
[arr[right], arr[rand]] = [arr[rand], arr[right]];
let mid = cutting(arr, arr[right], left, right);
if (typeof mid[2] === "number") {
return mid[2];
}
// k 在左边
if (mid[2]) {
sort(arr, left, mid[0], k);
} else {
// k 在右边
sort(arr, mid[1], right, k);
}
}
sort(arr, 0, arr.length - 1, 3);
console.log(arr);