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;
        }
    
  • 相关阅读:
    Linux内核RPC请求过程
    二分图
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 文本加密
    Java蓝桥杯 算法提高 九宫格
    Java蓝桥杯 算法提高 九宫格
  • 原文地址:https://www.cnblogs.com/JefferyChenXiao/p/12246444.html
Copyright © 2011-2022 走看看