剑指 Offer 40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入: arr = [3,2,1], k = 2
输出: [1,2] 或者 [2,1]
示例 2:
输入: arr = [0,1,2,1], k = 1
输出: [0]
限制:
0 <= k <= arr.length <= 100000 <= arr[i] <= 10000
基于快速排序的 partition
回顾快速排序中的 partition 操作,可以将元素arr[0]放入排序后的正确位置,并且返回这个位置index。利用 partition 的特点,算法流程如下:
如果index = k,说明第 k 个元素已经放入正确位置,返回前 k 个元素 如果k < index,前 k 个元素在[left, index - 1]之间,缩小查找范围,继续查找 如果index < k,前 k 个元素在[index + 1, right] 之间,缩小查找范围,继续查找 为了方便理解,可以使用2, 8, 1, 1, 0, 11, -1, 0这个例子在纸上画一下过程。
var getLeastNumbers = function(arr, k) {
const length = arr.length;
if (k >= length) return arr;
let left = 0,
right = length - 1;
let index = partition(arr, left, right);
while (index !== k) {
if (index < k) {
left = index + 1;
index = partition(arr, left, right);
} else if (index > k) {
right = index - 1;
index = partition(arr, left, right);
}
}
return arr.slice(0, k);
};
function partition(arr, start, end) {
const k = arr[start];
let left = start + 1,
right = end;
while (1) {
while (left <= end && arr[left] <= k) ++left;
while (right >= start + 1 && arr[right] >= k) --right;
if (left >= right) {
break;
}
[arr[left], arr[right]] = [arr[right], arr[left]];
++left;
--right;
}
[arr[right], arr[start]] = [arr[start], arr[right]];
return right;
}
方法二:
var getLeastNumbers = function(arr, k) {
arr.sort((a,b)=>a-b)
return arr.slice(0, k)
};