zoukankan      html  css  js  c++  java
  • 剑指offer_输入n个整数,找出其中最小的K个数

    最小的K个数

    题目描述

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

    本题无非就是排序,取前K个值。但选什么排序算法呢?

    基于堆排序算法,构建最大堆。时间复杂度为O(nlogk);
    如果用快速排序,时间复杂度为O(nlogn);
    如果用冒泡排序,时间复杂度为O(n*k);

    这类题目要考的应该是堆排序的改造。在n 较大,k较小的情况下。

    改造的堆排序:

    1.将前k个元素构造成最大堆(0~k-1)
    2.从k位开始,依次与最大堆的堆顶元素进行比较。如果比堆顶小,则该数与堆顶交换位置,维护最大堆
    3.最后从k-1~0的数是最小的k的数

    思考:
    为什么在求最小的k个数,不是建立最小堆而是建立最大堆???

    建立最大堆的情况下,判断从k~n-1位的数是否有可能是最小的k个数,只需与堆根进行比较,当它比跟堆大的时候,它肯定比堆内其他数都大,即它无希望排进前K个数。若有希望排进,那么需将目前堆内最大的数赶出,正好又是堆根,两者交换即可。

    代码:

    import java.util.*;
    public class Solution {
        public ArrayList<Integer>GetLeastNumbers_Solution(int[] input, int k) {
            ArrayList<Integer> array = new ArrayList<Integer>();
            if(input==null||input.length==0||k<=0||k>input.length){
                return array;
            }
            for(int i=k/2-1;i>=0;i--){
                buildMaxHeapSort(input,i,k);
            }
            for(int j=k;j<input.length;j++){
                if(input[j]<input[0]){
                    swap(input,0,j);
                    buildMaxHeapSort(input,0,k);
                }
            }
            for(int i=k-1;i>=0;i--){
                array.add(input[i]);
            }
            return array;
        }
    
        public void buildMaxHeapSort(int[] input,int i,int k){
            int leftchild=2*i;
            int rightchild=2*i+1;
            int larget=i;
            if(leftchild<k&&input[i]<input[leftchild]){
                larget=leftchild;
            }
            if(rightchild<k&&input[larget]<input[rightchild]){
                larget=rightchild;
            }
            if(larget!=i){
                swap(input,i,larget);
                buildMaxHeapSort(input,larget,k);
            }
        }
    
        public void swap(int[] input,int a,int b){
            int temp=input[a];
            input[a]=input[b];
            input[b]=temp;
        }
    }
  • 相关阅读:
    html的输出&,空格,大小于号
    html如何修改hr水平直线的粗细
    LODOP指定window默认打印机和临时默认打印机
    微软面试题: 找出二叉树上任意两个结点的最近共同父结点。
    说说自己对hibernate一级、二级、查询、缓存的理解。
    MySql中添加用户,新建数据库,用户授权,删除用户,修改密码
    修改MySQL的默认密码的四种小方法
    java中Scanner的nextLine()和next()的区别
    JAVA中String字符串比较equals()和equalsIgnoreCase()的区别
    HashMap与HashTable的区别
  • 原文地址:https://www.cnblogs.com/lingongheng/p/6444226.html
Copyright © 2011-2022 走看看