最小的K个数

最小的K个数

http://www.nowcoder.com/questionTerminal/6a296eb82cf844ca8539b57c23e6e9bf

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

/**
     * 1、取数组前k个数并构造大根堆;
     * 2、遍历输入数组K后面的数,每次和大根堆的根节点(堆顶)进行比较,若小于该节点,则替换;
     * 3、重新构建大根堆;
     * 4、循环结束,大根堆中的数即为原数组中最小的k个数;
     * 注意:大根堆是完全二叉树,最大的数为根节点,存储在数组中,根节点下标为0,
     *      若某父节点下标为【x】,则其左孩子为【2*x+1】 ,右孩子为【2*x+2】
     * 5、堆排序:从小到大排序。即将下标为【0】的数据(最大值)和当前的最后一位交换,此时
     *    最大值移动到数组最后一位。然后将剩下的len-1的数组再构造大根堆,将剩下数据中的
     *    最大值置于【0】位置,重复即可。
     * */
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> array = new ArrayList<>();
        if (input == null || input.length == 0 || k == 0 || k > input.length)
            return array;
        int[] result = new int[k];

        //将输入数组的前k个数放入结果数组,作为初始的k个数
        for (int i = 0; i < k; i++) {
            result[i] = input[i];
        }

        //将结果数据构建成大根堆
        buildMaxHeap(result, result.length);

        //遍历输入数组,每个数都与大根堆的根节点比较
        for (int i = k; i < input.length; i++) {
            if (input[i] < result[0]) {
                result[0] = input[i];
                //重构大根堆
                buildMaxHeap(result,result.length);
            }
        }

        // 调整大根堆,即堆排序
        for(int i = result.length - 1; i >= 1; i--)
        {
            swap(result,0, i);  // 将当前最大的数(w为0)放置到未排序数组的末尾
            buildMaxHeap(result,i);
        }

        //将大根堆内数据赋值给arraylist
        for (int i = 0; i < k; i++) {
            array.add(result[i]);
        }
        return array;
    }

    //构建成大根堆
    private void buildMaxHeap(int[] a, int len) {
        for (int i = len/2-1; i>=0; i--) {
            adjust(a, len, i);
        }
    }

    //将index节点和其左孩子、右孩子比较,通过交换将三个中最大的数值移动到index处
    private void adjust(int[] a, int len, int index) {
        int left = index*2+1;
        int right = index*2+2;
        if (left <= len-1 && a[left] > a[index]) {
            swap(a, left, index);
        }
        //注意这里是两个if,不能有else,因为父节点需要同时和左孩子和右孩子比较
        if (right <= len-1 && a[right] > a[index]) {
            swap(a, right, index);
        }
    }

    private void swap(int[] a, int i1, int i2) {
        int temp = a[i1];
        a[i1] = a[i2];
        a[i2] = temp;
    }
全部评论

相关推荐

05-14 20:34
门头沟学院 Java
窝补药贝八股:管他们,乱说,反正又不去,直接说680
点赞 评论 收藏
分享
小厂面经,也是我的处女面(30min)1.自我介绍2.spring&nbsp;boot的自动装配原理(好多类和接口的单词都忘了全称是啥了,就说了记得的单词,流程应该说对了吧)3.有用过redis吗?主要是用在实现什么功能(说了技术派用redis的zset来实现排行榜)5.有了解过Redisson吗?讲一下对于分布式锁的了解以及在什么场景下应用(说了秒杀场景)6.对mysql有了解吗?包括它的索引优化和创建(把想起来的全说了)7.了解设计模式吗?比如单例模式,为什么要使用单例模式,它的优点是什么(昨天刚看的设计模式)8.工厂模式有了解吗?主要的使用场景是?(也是昨天刚看的)9.场景题:有7个服务器,需要在早上十点定时的向数据库中的用户表中的用户发短信,如果做到发送的消息不重复,且如果发送失败了需要知道是到哪个用户失败了,这样下次就直接从这个用户开始(我答了用spring&nbsp;task来实现定时,用分布式锁来保证只有一份服务器可以发送消息,用消息队列来存储消息,然后用消息确认机制来保证错误信息的记录,以及在数据库或者业务层面完成消息消费的幂等性)10.场景题:如果在系统启动的时间就将数据库的所有用户相关的信息都读到一个hashmap中(这个没啥思路,没答好)27届的投了一个星期终于有一个面试了,大部分公司都只招26的
inari233:已oc,拒了
查看9道真题和解析
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务