剑指offer(29)最小的K个数

题目描述

输入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现在所在的下标返回
}

 

第二种:

略。

posted @ 2018-04-06 22:09  汕大小吴  阅读(1094)  评论(0编辑  收藏  举报