剑指 offer 数组算法题:最小的K个数

题目描述:输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

分析:

排序法,排序后取前 k 个。

分区法,以k为界限,遍历后半部分元素,若当前元素大于前 k 个元素中的最大值 max ,当前元素替换掉最大值 max。

大根堆法,维护一个 k 个 大小的大根堆,现将前k个元素入堆,然后遍历其余元素,若当前元素小于堆顶,就将堆顶元素弹出,当前元素入堆即可(堆的实现参考)。

求解:

// 排序法
function getLeastNumbers1(arr: number[], k: number): number[] {
  arr.sort((a, b) => a - b);
  return arr.slice(0, k);
}

// 分区法
function getLeastNumbers2(arr: number[], k: number): number[] {
  const len = arr.length;
  // 数组长度不大于 k,直接输出该数组
  if (len <= k) return arr;
  const indexOfMax = (arr: number[]): number => arr.reduce((prev, curr, i, a) => (curr > a[prev] ? i : prev), 0);
  const help = arr.slice(0, k);
  // k 个元素中最大元素的下标和值
  let maxIndex = indexOfMax(help);
  let max = help[maxIndex];
  for (let i = k; i < len; i++) {
    if (arr[i] < max) {
      // 当前元素比堆中最大元素更小,替换掉前k个元素中的最大元素
      help[maxIndex] = arr[i];
      maxIndex = indexOfMax(help);
      max = help[maxIndex];
    }
  }
  return help;
}

// 大根堆法
function getLeastNumbers3(arr: number[], k: number): number[] {
  const len = arr.length;
  // 数组长度不大于 k,直接输出该数组
  if (len <= k) return arr;
  if (k === 0) return [];
  const res: number[] = [];
  const heap = new Heap(); // 大根堆
  for (let i = 0; i < len; i++) {
    const element = arr[i];
    if (i < k) {
      heap.insert(element);
    } else if (element < heap.top()) {
      heap.delete();
      heap.insert(element);
    }
  }
  for (let i = 0; i < k; ++i) {
    res.push(heap.delete());
  }
  return res;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛定谔的猫96

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值