• 剑指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现在所在的下标返回
    }

    第二种:

    略。

  • 相关阅读:
    【CODEVS1380】没有上司的舞会
    【poj2248】Addition Chains
    【poj3070】Fibonacci
    【NOIP2006】开心的金明
    【Tyvj1359】收入计划
    【NOIP2015】跳石头
    【CODEVS1219】骑士游历
    暑假假期总结第六周
    暑假假期总结第五周
    暑假假期总结第四周
  • 原文地址:https://www.cnblogs.com/wuguanglin/p/GetLeastNumbers_Solution.html
Copyright © 2020-2023  润新知