《剑指offer》—— 29. 最小的K个数(Java)

题目描述

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

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        
    }
}

 

思路:

这题乍一看,可以用排序做。确实可以。但是如果数据特别大,大于内存呢?怎么排序?

所以这题虽然可以用排序做出来。但是醉翁之意不在酒啊~ 这题的考点其实是 最大堆 的实现。

不了解最大堆?看下面~

我们了解几个概念:

  1.  二叉堆是一种特殊的堆。

  2.  二叉堆就结构性质上来说就是一个完全填满的二叉树。
    满足结构性和堆序性。
    结构性:完全二叉树应该满足的树结构;
    堆序性:父节点的键值总是大于或等于(小于或等于)任何 一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

  3.  最大堆:当父节点的键值总是大于或等于任何一个子节点的键值。

  4. Java中,最大堆可用PriorityQueue实现大顶堆 (优先队列PriorityQueue是Queue接口的实现)。
    PriorityQueue默认是一个小顶堆,然而可以通过传入自定义的Comparator函数来实现大顶堆。
    如下代码实现了一个大顶堆。这里只是简单的传入一个自定义的Comparator函数,就可以实现大顶堆了。

    PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {                
                return o2 - o1;
            }
        });
    
    
    
    //顺便熟悉一下用 Java 8 中的 Lambda表达式的写法
    PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>((o1,o2), -> o2 - o1);

     

 

     5. PriorityQueue的几个方法:

add() //添加元素
size() //返回队列元素的个数
poll() //返回并删除队首元素

 

然后点到为止~更多相关知识,这里就不详细展开了。我们回到题目。

题目说:输入n个整数,找出其中最小的K个数。

  1. 那我们可以建立最大堆:maxHeap。
  2. 遍历这 n 个数,依次添加进最大堆maxHeap。
    因为maxHeap是最大堆,所以加进来的数会按照最大堆的规则排好,最大的在最上面。
  3. 每添加进一个数进 最大堆maxHeap,我们就判断一下最大堆maxHeap中的元素是否大于K个。
  4. 若小于K个,则直接添加。
    若大于K个,则将 最大堆maxHeap 堆顶的元素删除,也就是超过K个后,每次都将最大的元素删除。

一句话总结:创建一个最大堆,每次只读入一个数,且只保留最小的 K 个。

 

实现:

import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
   public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        if (k > input.length || k <= 0)
            return new ArrayList<>();
   PriorityQueue<Integer> maxHeap=new PriorityQueue<Integer>(new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {                
            return o2 - o1;
        }
    });
        for (int num : input){
            maxHeap.add(num);
            if(maxHeap.size() > k)
                maxHeap.poll();
        }
        return new ArrayList<>(maxHeap);
    }
}


//换成lambda表达式的写法~
import java.util.ArrayList;
import java.util.PriorityQueue;
import java.util.Comparator;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        if (k > input.length || k <= 0)
            return new ArrayList<>();
        PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1,o2) -> o2 - o1); 
        for (int num : input){
            maxHeap.add(num);
            if(maxHeap.size() > k)
                maxHeap.poll();
        }
        return new ArrayList<>(maxHeap);
    }
}

 

感觉应该讲清楚了~ 有疑问的,欢迎留言~

 

全部评论

相关推荐

作为带过好几个实习生的老mentor,我见过有同学带着一腔热血来实习,最后却只带走一份单薄的履历。实习,是你从学校到职场最关键的过渡期,它的价值远不止一份实习证明。今天,我不讲大道理,就从我作为Mentor的视角,给你们几条能立刻用上的建议。记住,你的目标不是当个好学生,而是成为一个值得信赖的职场新人。一、&nbsp;心态转变:从被动答题到主动解题这是我最想强调的一点。学生思维是:等待老师布置明确的作业,然后完成它。职场思维是:主动发现模糊的问题,然后解决它。反面事例:接到任务后,埋头就做,遇到困难不吭声,直到截止日期才说“这个我不会”。Mentor期待的是啥呢?首先是确认目标:接到任务后,先用自己的话复述一遍:“我理解这个任务是要达成XX效果,对吗?”&nbsp;确保方向没错。然后是主动思考:不要只带问题来,要带“选择题”。问“这个数据我不会查,我尝试了A和B方法都失败了,您看是方法C更合适,还是我有其他没考虑到的渠道?”&nbsp;这证明了你的思考和努力。最后是闭环思维:任务完成后,主动告知结果:“XX任务已完成,数据/文件已发您邮箱,并同步在团队网盘了。其中有个小发现是……,供您参考。”&nbsp;让一切有始有终。二、&nbsp;沟通方式:实习生的很多错误,都源于“想当然”和“不敢问”。反面教材:在做一个PPT时,因为不确定公司模板,就套用了自己觉得好看的模板,结果不能用。那么怎么确认,怎么提问呢?第一个,不懂就问,但别重复问:第一次问,是学习;同样的问题问第三次,就是不用心。准备一个笔记本,把关键信息、操作流程、注意事项都记下来。第二个,及时汇报,别等追问:特别是遇到卡壳或可能延期时,一定要提前说。Mentor不怕你慢,就怕你失联。没事儿更新一下进度:目前已完成80%,但在XX环节遇到点阻力,正在想办法沟通等回复,预计今天下班前确定结果,到时候给您,这样说能让人极度安心。第三个,珍惜1on1机会:和Mentor的定期沟通,不是你被动接受批评,而是你主动获取信息和反馈的黄金时间。提前准备好:a)&nbsp;本周工作进展;b)&nbsp;遇到的困惑/挑战;c)&nbsp;希望学习的新技能;d)&nbsp;对团队业务的任何好奇。三、&nbsp;工作习惯:&nbsp;专业性体现在细节里职业素养不是空话,它藏在每一个你容易忽略的细节中。1.&nbsp;邮件/沟通软件礼仪:邮件:标题清晰(如【实习生XX-XX项目周报】),正文称呼得体,结尾有落款。别用“在吗?”开头。工作群:别发表情包刷屏,沟通事情简明扼要。收到任务或通知,回复“收到,谢谢”,这是基本的确认和尊重。2.&nbsp;文件管理与命名:我会观察实习生的桌面,看他们的使用习惯,乱糟糟的桌面说明他没条理。文件命名要使用统一的命名规则:日期_项目名_内容_版本_姓名。例如:20231027_秋招海报_初版_张三。这能为整个团队节省大量沟通成本。3.&nbsp;对待杂活的态度:复印、整理数据、会议纪要……这些dirty&nbsp;work是不可避免的。但优秀的人是能从中找到价值的:整理数据时,可以留意数据之间的关联或异常,做会议纪要时,可以梳理出会议的决策和待办事项。四、&nbsp;终极目标:带走三样东西1.&nbsp;一段能讲出STAR法则的实战经历:这直接决定了你未来求职简历的厚度。2.&nbsp;一位可以为你未来背书的Mentor/同事:好好表现,离职时保持联系,他们可能成为你未来求职的推荐人和内推渠道。3.&nbsp;对行业和岗位的真实认知:通过这次实习,你想清楚自己是更热爱这个行业,还是想赶紧跑路?这个答案,价值千金。最后,作为你们的Mentor,我想说:大胆去试,勇敢去问,别怕犯错。实习期是你犯错成本最低的时候。展现出你的靠谱、主动和思考,我们做Mentor的,会非常乐意把更核心的任务交给你,因为带你,也是在为团队培养未来的战友。希望这些建议能帮你少走弯路,打一场漂亮的实习战!
家族企业:实习一年比在大学多年都有用
第一次找实习,我建议__
点赞 评论 收藏
分享
2025-11-11 20:14
已编辑
安徽工业大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务