题目
输入整数数组 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]
解题思路
调用API
调用数组排序sort方法,将数组排序;返回前K个数
代码
var getLeastNumbers = function(arr, k) {
arr.sort((a,b)=>a-b);
return arr.slice(0,k)
};
借用快速排序
在上述思路中调用sort方法将数组整个排序,实际只需要知道排序K个数即可得到答案;所以上面的思路还有继续优化的空间
已知:题目要求返回最小的k个数,并没有要求返回有序的最小K个数;
所以可以借用快排思想;
快排
找到基准值 pivot ,大于基准值的放在基准值右侧,小于基准值的放在基准值左侧;
假如基准值正好在K这个位置,是不是基准值左侧的数据就是最小的k个数呀?
举个栗子:
现在有数组array = [5,2,6,11,8,4]
graph LR
5 --> 2--> 6 --> 11--> 8--> 4
第1步:对数组从 0 到array.length-1 找基准值,假设依数组第一个数为基准值;当前数组基准值为5;
第2步:快排思想排序,大于5的放在数组右侧,小于数组的放在左侧
graph LR
2 --> 4 -->5--> 6 --> 11--> 8
第3步:假设此时K=2;基准值5在排序后的数组下标为index;此时k===index,直接返回数组前K个即可;
第4步:第3步的另一个分支,如果k大于2;此时index=2;index < k;所以 index+1 到 array.length-1 执行第1步
第3步:第3步的另一个分支,如果k小于2;此时index=2;index > k;所以 1 到 index 执行第1步
根据上述思路执行代码如下;
着重理解partition函数
代码
var getLeastNumbers = function (arr, k) {
// 快速排序方法
const len = arr.length
let left = 0
let right = len - 1
let idx = partition(arr, left, right)
while (idx !== k) {
if (idx < k) {
left = idx + 1
} else {
right = idx - 1
}
idx = partition(arr, left, right)
}
return arr.slice(0, k)
function partition(arr, start, end) {
let pivot = arr[start]
let index = start
for (let i = start; i <= end; i++) {
if (arr[i] < pivot) {
index++
;[arr[i], arr[index]] = [arr[index], arr[i]]
}
}
;[arr[start], arr[index]] = [arr[index], arr[start]]
return index
}
}