题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
题目分析
这题有两种方法来做。
第一种就是基于partition的方法,详见我的另一篇文章:基于快排思想查找第K大的数或第K小的数。
第二种就是利用一个长度为k的额外容器,来存储最小的K个数字。容器未满则填满,再添加数字是,将数字和容器的最大值比较,小的话就替换,大的话舍去。
这个容器要求可以直接得到最大值、能删除最大值,能添加值。那么很容易想到应该用最大堆当这个容器,当然也可以用红黑树来实现。由于事先容器比较复杂,这里就不给出代码了。
代码
第一种:
function GetLeastNumbersSolution(input, k) { if (input.length === 0 || k > input.length || k < 1) return []; const left = 0, right = input.length - 1; let key = partition(input, left, right); while (key !== k - 1) { if (key > k - 1) { key = partition(input, left, key - 1); } else { key = partition(input, key + 1, right); } } const res = input.slice(0, key + 1); res.sort((a, b) => a - b); return res; } function partition(a, left, right) { const key = a[left]; // 一开始让key为第一个数 while (left < right) { // 扫描一遍 while (key <= a[right] && left < right) { // 如果key小于a[right],则right递减,继续比较 right--; } [a[left], a[right]] = [a[right], a[left]]; // 交换 while (key >= a[left] && left < right) { // 如果key大于a[left],则left递增,继续比较 left++; } [a[left], a[right]] = [a[right], a[left]]; // 交换 } return left; // 把key现在所在的下标返回 }
第二种:
略。