1. 题目描述
输入 n 个整数,找出其中最小的 k 个数。例如输入 4、5、1、6、2、7、3、8 这 8 个数字,则最小的 4 个数字是 1、2、3、4。
2. 思路分析
利用“快速排序”的中的 partition 操作:返回 index,小于 index 对应元素的元素都放在了左边,大于 index 对应元素的元素都放在右边。
利用这个特性,只要我们的 partition 返回值是 k - 1,那么数组中前 k 个元素已经被摆放到了正确位置,直接遍历输出即可。
由于不需要排序全部,整体的时间复杂度是 O(N)。但美中不足的是:要在原数组操作,除非用 O(N)的空间来做拷贝。除此之外,针对海量动态增加的数据,也不能很好处理。这种情况需要用到“最大堆”,请前往《堆》章节查看。
3. 代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| function partiton(arr = [], start, end) { const length = arr.length if (!length) { return null }
let v = arr[start], left = start + 1, right = end
while (1) { while (left <= end && arr[left] <= v) ++left while (right >= start + 1 && arr[right] >= v) --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 }
function getKthNumbers(nums = [], k) { if (k <= 0) { return null }
const length = nums.length const result = new Array(k) let start = 0, end = length - 1 let index = partiton(nums, start, end) while (index !== k - 1) { if (index > k - 1) { end = index - 1 index = partiton(nums, start, end) } else { start = index + 1 index = partiton(nums, start, end) } }
for (let i = 0; i < k; ++i) { result[i] = nums[i] }
return result }
console.log(getKthNumbers([4, 5, 1, 6, 2, 7, 3, 8], 4)) console.log(getKthNumbers([10, 2], 1))
|