【剑指offer】-29-最小的k个数

最小的K个数

https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=13&&tqId=11182&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

1. 异常值分析,再Arrays.sort数组排序后输出前k个

import java.util.ArrayList;
import java.util.Arrays;

public class Solution {
     public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> list= new ArrayList<>();
         if(k>input.length || input.length==0) return list;
        Arrays.sort(input);
        for(int i=0;i<k;i++){
            list.add(input[i]);
        }
        return list;
    }
}

2. 利用堆

  • 堆是一个完全二叉树的数组,用数组表示堆并初始化,形成大根堆要不断维护堆中的节点,并且从最后一个非叶子节点(length/2-1)开始从下往上维护。

  • 对于n个整数中最小的K个数的查找,可以使用各种排序算法:冒泡/堆排/快排/希尔排序等等。将此n个整数从小到大排序之后,前k个数就是所求的结果。

  • 但是当原数组中的数据顺序不可修改,并且n的值过于大的时候,各种排序算法要将n个数加载到内存中,即:如果是海量数据中查找出最小的k个数,那么这种办法是效率很低的。接下来介绍另外一种算法:

  • ** 创建一个大小为k的数组,遍历n个整数,如果遍历到的数小于大小为k的数组的最大值,则将此数与其最大值替换。**

  • 由于每次都要拿n个整数和数组中的最大值比较,所以选择大根堆这一数据结构(大家要分清楚大根堆这一数据结构和堆排序之间的区别:堆排序是在大根堆这一数据结构上进行排序的一种排序算法,一个是数据结构,一个是算法)

    public ArrayList<Integer> GetLeastNumbers_Solution(int[] input, int k) {
          ArrayList<Integer> list = new ArrayList<>();
          if (k > input.length || input.length == 0 || k == 0) return list;
          int[] a = new int[k];//大顶堆实际上是一个完全二叉树的数组,所以用数组来初始化大顶堆
          if (k >= 0) System.arraycopy(input, 0, a, 0, k);//大顶堆初始化为input的前k个数
          int x = k / 2 - 1;//最后一个非叶子节点
          //从最后一个非叶子节点开始从下往上维护大顶堆
          for (int i = x; i >= 0; i--) {
              initiate(a, k, i);
          }
    
          // 去遍历剩余的len - k个节点
          for (int i = k; i < input.length; i++) {
              if (input[i] < a[0]) {
                  a[0] = input[i];
                  initiate(a, k, 0);
              }
          }
    
          //调整大顶堆为升序数组再输出
          for (int i = a.length - 1; i > 0; i--) {
              int temp = a[i];
              a[i] = a[0];
              a[0] = temp;
              initiate(a, i, 0);//再维护大顶堆
          }
    
          for (int value : a) {
              list.add(value);
          }
          return list;
      }
    
      /**
       * 初始化堆的函数,就是维护每一个节点的位置的函数
       *
       * @param a   数组->堆
       * @param len 堆的个数
       * @param x   要维护的节点的下标
       */
      private void initiate(int[] a, int len, int x) {
          int temp = a[x];
          for (int k = 2 * x + 1; k < len; k = k * 2 + 1) {
              if ((k + 1) < len && a[k + 1] > a[k]){ // 一定是(k + 1) < len 在左边,因为&&短路与,如果左边的条件不成立,那么不会执行右边,否则可能会有异常!!
                  //找到左右孩子的最大值的下标k
                  k++;
              }
              if (a[k] > temp) {
                  a[x] = a[k];
                  x = k;
              } else {
                  break;//跳出for循环
              }
          }
          a[x] = temp;
      }

3. 插入排序,对前k个元素从小到大排序,迭代更新前k个元素

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {

        ArrayList<Integer> result = new ArrayList<Integer>();
        if(k<= 0 || k > input.length)return result;
        //初次排序,完成k个元素的排序
        for(int i = 1; i< k; i++){
            int j = i-1;
            int unFindElement = input[i];
            while(j >= 0 && input[j] > unFindElement){
                input[j+1] = input[j];
                j--;
            }

            input[j+1] = unFindElement;
        }
        //遍历后面的元素 进行k个元素的更新和替换
        for(int i = k; i < input.length; i++){
            if(input[i] < input[k-1]){
                int newK = input[i];
                int j = k-1;
                while(j >= 0 && input[j] > newK){
                    input[j+1] = input[j];
                    j--;
                }
                input[j+1] = newK;
            }
        }
        //把前k个元素返回
        for(int i=0; i < k; i++)
            result.add(input[i]);
        return result;
    }
}

Top K问题参考:https://www.cnblogs.com/ccdev/archive/2012/09/12/2682246.html

全部评论

相关推荐

霁华Tel:秋招结束了,好累。我自编了一篇对话,语言别人看不懂,我觉得有某种力量在控制我的身体,我明明觉得有些东西就在眼前,但身边的人却说啥也没有,有神秘人通过电视,手机等在暗暗的给我发信号,我有时候会突然觉得身体的某一部分不属于我了。面对不同的人或场合,我表现出不一样的自己,以至于都不知道自己到底是什么样子的人。我觉得我已经做的很好,不需要其他人的建议和批评,我有些时候难以控制的兴奋,但是呼吸都让人开心。
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务