力扣剑指offer之最小的k个数

输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
示例 1:
输入:arr = [3,2,1], k = 2
输出:[1,2] 或者 [2,1]
示例 2:
输入:arr = [0,1,2,1], k = 1
输出:[0]

解析:本题力扣标签是简单,猛的一看确实是简单题,这不就是一个排序加一个前k位吗??所以你可以直接写出下面代码:

public int[] getLeastNumbers(int[] arr, int k) {
        Arrays.sort(arr);
        int[] result = new int[k];
        for(int i = 0; i < k; i++){
            result[i] = arr[i];
        }

        return result;
    }

一试运行,还真给过了。但是,你细想,这是剑指offer里的题,也就是说大概率面试题,如果你是面试官,出这么一道题,面试者直接排序给你输出了,你会认为它有什么能力吗????所以在面试场上,千万不要这样排序输出完事。

那该怎么做呢??我们可以想到优先队列,如果我们使用优先队列来形成堆排序,做这个题,是不是会更让面试官看到我们与别人的不同点呢?
现在我们面临几个问题:
1)用优先级队列实现前k个小值,那么我们应该使用优先级队列实现的小根堆还是大根堆呢??
2)得到优先级队列实现的堆后,如何得到题目要求输出的数组返回值结果呢?

针对第一个问题,我们假设选择小根堆,那堆中存的就是前k小值。堆顶元素存储的就是前k小中的最小值。那么我们在挑选最小的前k个值时,如果数组中值大于堆顶元素,那么直接跳过即可,执行下一个元素。但是如果数组中的值小于堆顶元素呢?那么就说明该值要放入堆中,此时就要有一个值需要移除出堆,这个值应该是堆中元素最大值,而堆顶元素确实最小值,此时最大值并不好得到,因此我们舍弃小根堆。
如果我们选择大根堆,那么在数组内元素和堆顶元素比较时,如果大于堆顶元素,那么直接进入下一个数比较。如果小于呢?那就说明当前数组元素小于堆内元素,那么就要对堆内元素更新,将其加入堆内排序,此时需要将堆内最大元素输出,那就是栈顶元素啊,所以直接把第一个poll即可。

针对第二个问题,我们直接看代码实现过程即可。

public int[] getLeastNumbers(int[] arr, int k) {
        
        int[] result = new int[k];
        if(k == 0){
            return result;
        }

        PriorityQueue<Integer> queue = new PriorityQueue<Integer>(new Comparator<Integer>() {
            public int compare(Integer num1, Integer num2) {
                return num2 - num1;
            }
        });

        for(int i = 0; i < k; i++){
            queue.add(arr[i]);
        }

        for(int i = k; i < arr.length; i++){
            if(queue.peek() > arr[i]){
                queue.poll();
                queue.offer(arr[i]);
            }
        }

        for(int i = 0; i < k; i++){
            result[i] = queue.poll();
        }
        return result;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值