剑指offer打卡Day16:最小的k个数(优先队列与快速排序)

剑指offer打卡Day16:最小的k个数(优先队列与快速排序)

题目描述

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

示例

输入

[4,5,1,6,2,7,3,8],4

返回值

[1,2,3,4]

解析:

  • 万物皆可用暴力法破解:

    • 对数组进行判断,(判断非空与 k>input.length 或者K==0 等情况)
    • 对数组进行排序,默认排序都是从小到大进行排序
    • 遍历数组,同时记得维护非重和count计数(以k为标准)
    • 将数组元素存入Arraylist并返回
  • 暴力法确实可以解决问题,但是老是靠暴力解决不了问题啊,就跟现在的工作铲屎一样学不了东西

  • 查阅资料发现可以用优先队列来完成这题

  • 优先队列PriorityQueue

    • 标准定义:

      PriorityQueue类在Java1.5中引入。PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。

    • 作用:

      优先队列的作用是能保证每次取出的元素都是队列中权值最小的(Java的优先队列每次取最小元素,C++的优先队列每次取最大元素)。这里牵涉到了大小关系,元素大小的评判可以通过元素本身的自然顺序(natural ordering),也可以通过构造时传入的比较器Comparator,类似于C++的仿函数)。

    • 举两个例子:

      1. 作业系统中的调度程序,当一个作业完成后,需要在所有等待调度的作业中选择一个优先级最高的作业来执行,并且也可以添加一个新的作业到作业的优先队列中。
      2. 每日交易时段生成股票报告的应用程序中,需要处理大量数据并且花费很多处理时间。客户向这个应用程序发送请求时,实际上就进入了队列。我们需要首先处理优先客户再处理普通用户。在这种情况下,Java的PriorityQueue(优先队列)会很有帮助。
  • 快速排序:

    • 快速排序(QuickSort )是常用到的效率比较高的一种排序算法,在面试过程中也经常提及,出了冒泡再复习下这个快排算法。

    • 执行步骤总结:

      • 从数列中挑出一个元素,称为 “基准”(pivot);

      • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;

      • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;

        十大经典排序算法动画与解析,看我就够了!(配代码完全版)–作者:五分钟学算法

    • 图解执行步骤:

      • 以数列[6,1,2,7,9,3,4,5,10,8]为例

      • 具体过程如下图:

      在这里插入图片描述

      • 配合图片讲解算法:

        • Step1:

          • 以数列首位(index == 0)为基准(pivot),right为最后一位(index == arr.length-1),left为第二位(index == 1),开始遍历;

          • 从right开始,向左(index–)开始寻找比pivot小的元素,移动一位后left也开始向右(index++)移动寻找比pivot大的元素,若找到了他们要的便会停止移动,并交换L与R

          • 如图:

            • 5与7交换,4与9交换
          • 当遍历至left == right之后,(L,R)与pivot交换

          • 执行完毕后变为:

            [3,1,2,5,4,6,9,7,10,8]

            此时发现以原pivot(6)为分界线,做左边的数列都小于6,右边的数列都大于6

        • Step2:

          • 将数列[3,1,2,5,4,6,9,7,10,8]以6分成左右两个小数列(命名为A、B)
          • 并分别对两个小组小数列进行类似Step1的操作
          • A => [1,2,3,4]
          • B => [7,8,9,10]
        • Step3:

          • 合并起来即可
        • 综上,其实就是一直在重复Step1上的步骤:找pivot与遍历,因此可以用递归来实现

    • 代码解析:

      //Java 代码实现
      public class QuickSort implements IArraySort {
             
      
          @Override
          public int[] sort(int[] sourceArray) throws Exception {
             
              // 对 arr 进行拷贝,不改变参数内容
              int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
      
              return 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值