zoukankan      html  css  js  c++  java
  • 剑指Offer对答如流系列

    面试题40:最小的k个数

    题目描述

    输入n个整数,找出其中最小的k个数。例如输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

    问题分析

    最容易想到的方法就是排序,取相应数字的元素即可。我这里为了方便直接使用了快排来做这个。

    想拉开与别人的差距,难免需要优化时间效率,我们可以这样做:依次遍历n个整数,用一个容器存放最小的k个数字,每遇到比容器中最大的数字还小的数字时,将最大值替换为该数字。容器可以使用最大堆或者红黑树来实现。堆相比红黑树更容易实现,我们这里采用堆。

    问题解答

    思路一(不推荐)

        public ArrayList<Integer> GetLeastNumbers(int [] input, int k) {
            ArrayList<Integer> leastNumbers = new ArrayList<>();
            if(input==null || k<=0 || k>input.length) {
                return leastNumbers;
            }
    
            int start=0;
            int end=input.length-1;
            int index=partition(input,start,end);
    
            while(index!= k-1){
                if(index< k-1){
                    start=index+1;
                    index=partition(input,start,end);
                }else{
                    end=index-1;
                    index=partition(input,start,end);
                }
            }
            for(int i=0;i<k;i++){
                leastNumbers.add(input[i]);
            }
            return leastNumbers;
        }
    
        private int partition(int[] arr, int start,int end){
            int pivotKey=arr[start];
            while(start<end){
                while(start<end && arr[end]>=pivotKey) {
                    end--;
                }
                swap(arr,start,end);
                while(start<end && arr[start]<=pivotKey){
                    start++;
                }
                swap(arr,start,end);
            }
            return start;
        }
    
        private void swap(int[] arr, int i,int j){
            int temp=arr[i];
            arr[i]=arr[j];
            arr[j]=temp;
        }
    

    思路二(推荐)

      public ArrayList<Integer> GetLeastNumbers(int [] input, int k) {
            ArrayList<Integer> leastNumbers = new ArrayList<>();
            if(input==null || k<=0 || k>input.length) {
                return leastNumbers;
            }
            int[] numbers=new int[k];  //用于放最小的k个数
            //先放入前k个数
            System.arraycopy(input, 0, numbers, 0, k);
    
            for(int i = k/2-1; i>=0; i--){
                adjustHeap(numbers,i,k-1);//将数组构造成最大堆形式
            }
            for(int i = k; i<input.length; i++){
                if(input[i]<numbers[0]){ //存在更小的数字时
                    numbers[0]=input[i];
                    adjustHeap(numbers,0,k-1);//重新调整最大堆
                }
            }
            for(int n:numbers)
                leastNumbers.add(n);
            return leastNumbers;
        }
    
        //最大堆的调整方法
        private void adjustHeap(int[] arr,int start,int end){
            int temp=arr[start];
            int child=start*2+1;
            while(child<=end){
                if(child+1<=end && arr[child+1]>arr[child]) {
                    child++;
                }
                if(arr[child]<temp) {
                    break;
                }
                arr[start]=arr[child];
                start=child;
                child=child*2+1;
            }
            arr[start]=temp;
        }
    
  • 相关阅读:
    使用SecureCRT连接虚拟机中Linux系统的详细方法以及虚拟网络配置方法
    虚拟机快照克隆多台的方法
    Linux虚拟机网络设置
    Hadoop学习笔记之一:Hadoop IPC
    webpack超详细配置, 使用教程(图文)
    webstrom提示不见了
    vuejs实现本地数据的筛选分页
    关于手机端audio无法自动播放问题解决方法
    计算机实现加法的学习心得
    计算机编码随记
  • 原文地址:https://www.cnblogs.com/JefferyChenXiao/p/12246444.html
Copyright © 2011-2022 走看看