• 剑指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;
        }
    
  • 相关阅读:
    docker 学习
    grpc 学习
    ubuntu 完全干净的卸载docker
    numpy学习
    2020年假期sql excel文件 获取
    (a2b_hex)binascii.Error: Non-hexadecimal digit found
    数据库索引学习
    网络基础之网络协议
    Day11 进程相关
    基于socket套接字的网络通讯
  • 原文地址:https://www.cnblogs.com/JefferyChenXiao/p/12246444.html
Copyright © 2020-2023  润新知