前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java集合与数据结构——优先级队列的使用及练习

Java集合与数据结构——优先级队列的使用及练习

作者头像
RAIN7
发布2021-08-16 16:23:21
6400
发布2021-08-16 16:23:21
举报
文章被收录于专栏:RAIN7 de 编程之路

本文内容介绍大纲

接上篇 Java集合与数据结构——优先级队列(堆)

一、对象比较的方法

  上节课我们讲了优先级队列,优先级队列在插入元素时有个要求:

 插入的元素不能是null或者元素之间必须要能够进行比较,为了简单起见,我们只是插入了Integer类型,那优先级队列中能否插入自定义类型对象呢?

  我们先不用优先级队列来比较,先来看自定义类型如何进行比较…

  我们写了一个 Student 的一个类,类内部有姓名和年龄两个属性,我们直接通过数组类进行比较…

我们来看结果

  那么我们一个自定义类型中有两个属性甚至多个属性的情况下,如何进行比较呢?

1.重写 compareTo 方法

  首先在 自定义类后面 实现 Comparable 接口,然后重写 compareTo 方法.

在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。

在这里 重写的compareTo 方法里 ,以年龄为基准进行排序

现在我们再来运行

这种比较方法有一个缺点:

 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序. 我们只能通过 compareTo 里的规则进行排序.

2.基于比较器的比较

1.用户自定义比较器类,实现Comparator接口 2.覆写Comparator中的compare方法

我们来写一个 年龄的比较器

在数组排序时,我们可以将比较器作为参数,进行比较

我们来看运行结果:

  这种比较的方法我非常推荐,因为 对内部类不影响,我们只是建立了一个外部的比较器 ,当比较时 ,我们可以将比较器作为参数进行排序的.

二、Java 优先级队列的 比较

  上节课我们学习了堆,这里我们就来看看 当自定义类的数据如何放入堆中.

1.如何比较

  集合框架中的PriorityQueue底层使用堆结构,因此其内部的元素必须要能够比大小,PriorityQueue采用了:

Comparble和Comparator两种方式。

1. Comparble是默认的内部比较方式,如果用户插入自定义类型对象时,该类对象必须要实现Comparble接口,并覆写compareTo方法 2. 用户也可以选择使用比较器对象,如果用户插入自定义类型对象时,必须要提供一个比较器类,让该类实现Comparator接口并覆写compare方法。

  我们可以在构造 PriorityQueue 时,直接将比较器 作为参数 比较.

我们来看结果:

PriorityQueue 构造方法

2.优先级队列解决 TOPK 问题

  我们要在下列数组中找到 最小的三个数据

int 8 arr = { 9,4,6,2,3,8,1,7 } ;

  建立一个 K=3 的 大堆,依次遍历,比堆顶元素 小的入队,堆顶元素出队.

建立一个 K=3 的大堆

  我们直接在 内部实现一个 comparator 的方法,o2 - o1是建立大堆,o1 - o2 是建立小堆.

  TOPK 问题的思路我们在上一篇文章已经说的很清楚了,不明白的同学可以看一下 我的优先级队列的那一篇博客~~

完整代码展示:

运行结果:

运行成功,答案也正确了~~

三、练习

好了,之前铺垫了那么多,我们给大家来两道练习题:

1.查找和最小的 K 对数字

leetcode 题目链接——查找和最小的 K 对数字

思路:

  本题使用topk的经典解法。利用优先级队列PriorityQueue,构造大小为K的大根堆。

1、堆没有放满的情况下,直接往堆里面添加,直到添加到K的大小。 2、堆的大小等于K之后,每次存放数对的时候,和堆顶比较,如果堆顶的元素大于当前的数对,那么出队。然后添加当前数对。 3、直到遍历完两个数组。

注意点:

1、 遍历两个数组的时候,大小要和k取最小值。防止超出 时间限制,爆内存,给我们两个长度都很大的数组,要求取前10个最大的数,我们光是遍历完这两个数组都会超出时间限制,因为这两个数组是升序的,所以我们不必完全遍历,取 arr.length 与 K 的最小值同样能达到效果. 2、取结果的时候注意,一定要判断队列此时空不空,队列虽然大小是k,但是有可能放不满k个。

完整代码展示:

运行结果:

2.最后一块石头的重量

leetcode 题目链接——最后一块石头的重量

题目描述

思路:

将所有石头的重量放入最大堆中。每次依次从队列中取出最重的两块石头 a 和b,必有 a ≥ b 。 如果 a > b,则将新石头a−b 放回到最大堆中; 如果a = b,两块石头完全被粉碎,因此不会产生新的石头。重复上述操作,直到剩下的石头少于 2 块。 最终可能剩下 1 块石头,该石头的重量即为最大堆中剩下的元素,返回该元素;也可能没有石头剩下,此时最大堆为空,返回 0。

代码展示:

  好了今天的知识就分享到这里,希望大家多多练习,熟练掌握,感谢大家的欣赏与关注!!

谢谢欣赏!

未完待续…

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、对象比较的方法
    • 1.重写 compareTo 方法
      • 2.基于比较器的比较
      • 二、Java 优先级队列的 比较
        • 1.如何比较
          • 2.优先级队列解决 TOPK 问题
          • 三、练习
            • 1.查找和最小的 K 对数字
              • 2.最后一块石头的重量
              • 未完待续…
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档