目录

实现一个大根堆

优先级队列

Comparable和Compator区别

compareTo方法

TopK问题


TopK问题常见题型为求最大(最小)的K个值。

我们一般拿堆来解决。

堆:二叉堆首先是一颗完全二叉树

二叉堆结点间的关系满足:

大根堆: 根节点是整棵树的最大值,对于它的任意子树,堆中根节点的值>=子树中的结点值。

小根堆: 根节点是整棵树的最小值,对于它的任意子树,堆中根节点的值<=子树中的结点值。

TopK题型解决:取大用小,取小用大。

(取前100个比较小的树用大根堆,

取前100个比较大的树用小根堆)

实现一个大根堆

package ds.bin_tree.bin_tree_heap;import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;/*** 大根堆* @Author liusifan* @Data 2022/2/28 20:30*/
public class MaxHeap {List<Integer> arr;public MaxHeap(){this(10);}//初始化堆大小public MaxHeap(int size){arr=new ArrayList<>(size);}public void siftUp(int k){//上浮条件:结点值大于父节点值||走到根结点while (k>0&&arr.get(k)>arr.get(parent(k))){swap(k,parent(k));k=parent(k);}}/*** 将任意数组堆化* @param arr2*/public MaxHeap(int[] arr2){arr=new ArrayList<>(arr2.length);MaxHeap maxHeap=new MaxHeap();for (int i:arr2){arr.add(i);}//从最后一个非叶子结点开始,依次进行元素下沉for (int i=parent(arr.size()-1);i>=0;i--){siftDown(i);}}/*** 元素的下沉操作* @param k*/public void siftDown(int k){//终止条件:走到叶子结点了,k的左子树已经大于数组长度了while (leftTree(k)<arr.size()){int i=leftTree(k);if (i+1<arr.size()&&arr.get(i+1)>arr.get(i)){i=i+1;}if (arr.get(k)>arr.get(i)){break;}else{swap(k,i);k=i;}}}/*** 取出当前堆中元素最大值* @return*/public int extractMax(){if (isEmpty()){throw new NoSuchElementException("heap is empty");}int max=arr.get(0);arr.set(0,arr.get(arr.size()-1));arr.remove(arr.size()-1);siftDown(0);return max;}/*** 获取最大元素* @param* @return*/public  int peekMax(){if (isEmpty()){throw new NoSuchElementException("heap is empty");}return arr.get(0);}private void swap(int i, int j) {int temp=arr.get(i);//arr.set(元素下标,元素值)arr.set(i,arr.get(j));arr.set(j,temp);}public void add(int val){arr.add(val);siftUp(arr.size()-1);}/*** 找到父节点* @param k* @return*/private int parent(int k){return (k-1)/2;}private boolean isEmpty(){return arr.size()==0;}/*** 根据索引找到左子树(2k+1)* @param k* @return*/private int leftTree(int k){return (2*k)+1;}/*** 根据索引找到右子树(2k+2)* @param k* @return*/public int rightTree(int k){return (2*k)+2;}@Overridepublic String toString() {return arr.toString();}
}

优先级队列

优先级队列:看起来是队列,底层是基于堆的实现,按照元素的优先级大小动态出队。

(JDK内置优先级是最小堆)

package ds.bin_tree.bin_tree_heap;import java.util.*;
import java.util.PriorityQueue;/*** JDK内置优先级是最小堆* @Author liusifan* @Data 2022/3/6 22:19*/
public class PriorityQueueTest {public static void main(String[] args) {//通过构造方法传入比较器//默认是最小堆,“值”(比较器comparator返回的值)越小,优先级越高//传入降序比较器。
//        Queue<Student> queue=new PriorityQueue<>(new StudentComDesc());//匿名内部类,创建一个Comparator接口的子类,这个子类只使用一次Queue<Student> queue=new PriorityQueue<>(new Comparator<Student>(){@Overridepublic int compare(Student o1, Student o2) {return o1.getAge()- o2.getAge();}});//Lambda表达式,函数式编程
//      Queue<Student> queue=new PriorityQueue<>((o1, o2) -> o1.getAge()-o2.getAge());Student  stu = new Student("张三", 19);Student stu2 = new Student("李四", 27);Student stu3 = new Student("王五", 25);queue.offer(stu);queue.offer(stu2);queue.offer(stu3);while (!queue.isEmpty()){System.out.println(queue.poll());}
//        Student[] students={stu,stu2,stu3};
//        Arrays.sort(students);
//        System.out.println(Arrays.toString(students));
//        System.out.println(stu.compareTo(stu2));
//        System.out.println(stu.compareTo(stu3));
//        Student[] students={stu,stu2,stu3};
//        Arrays.sort(students,new StudentCom());
//        System.out.println(Arrays.toString(students));}
}
//从小到大顺序
class StudentCom implements Comparator<Student>
{@Overridepublic int compare(Student o1, Student o2) {return o1.getAge()-o2.getAge();}
}
//从大到小顺序
class StudentComDesc implements Comparator<Student>
{@Overridepublic int compare(Student o1, Student o2) {return o2.getAge()-o1.getAge();}
}
class Student
{private String name;private int age;public Student(String name,int age){this.age=age;this.name=name;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}

Comparable和Compator区别

比较器Compartor:新建一个类来对内容进行比较。

一个类实现了Comparabe接口,说明该类具备了可比较大小的能力。类本身具备可比较能力。

如:

class Student implements Comparable<Student>
{private String name;private int age;public Student(String name,int age){this.name=name;this.age=age;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {return this.getAge()-o.getAge();}
}

compareTo方法

  • 返回参与比较的前后两个字符串的ASCII码的差值,如果两个字符串首字母不同,则该方法返回首字母的ASCII码的差值。
    String str="a";String str2="c";//结果为-2,a的ASCII码减去c的ASCII码System.out.println(str.compareTo(str2));
  • 参与比较的两个字符串如果首字符相同,则比较下一个字符,直到有不同的为止,返回该不同的字符的asc码差值。
    String str="bb";String str2="be";//结果为-3System.out.println(str.compareTo(str2));
  • 如果两个字符串不一样长,可以参与比较的字符又完全一样,则返回两个字符串的长度差值。
    String str="cc";String str2="cc123456";//结果为-6,返回的是两个字符串长度差值System.out.println(str.compareTo(str2));
  • 返回为正数表示a1>a2, 返回为负数表示a1<a2, 返回为0表示a1==a2。
    String str="cc";String str2="ca";//结果为2System.out.println(str.compareTo(str2));
  • int类型不能用comparTo进行比较,只有包装类才可以,即Integer、Character ,String等包装类
    Character a='c';Character b='b';//返回1System.out.println(a.compareTo(b));Integer num=5;Integer num2=10;//返回-1System.out.println(a.compareTo(b));

TopK问题

package ds.bin_tree.bin_tree_heap.leetcode;import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;/*** 找出数组中最小的k个数。以任意顺序返回这k个数* @Author liusifan* @Data 2022/3/9 18:24*/
public class Num17_14 {public int[] smallestK(int[] arr, int k) {if (arr.length==0||k==0){return new int[0];}//构造一个最大堆,JDK默认最小堆,使用比较器改为最大堆。Queue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;}});for (int i:arr){if (queue.size()<k){queue.offer(i);}else{int peek=queue.peek();if (i>peek){continue;}//当前元素<堆顶元素,先出队,再把当前元素入队else{queue.poll();queue.offer(i);}}}int[] ret=new int[k];for (int i=0;i<k;i++){ret[i]=queue.poll();}return ret;}
}

package ds.bin_tree.bin_tree_heap.leetcode;import java.util.*;/*** 前k个高频元素* @Author liusifan* @Data 2022/3/11 10:19*/
public class Num347 {private class Freq implements Comparable<Freq>{private int key;private int times;public Freq(int key, int times) {this.key = key;this.times = times;}@Overridepublic int compareTo(Freq o) {return this.times-o.times;}}public int[] topKFrequent(int[] nums, int k) {int[] ret=new int[k];Map<Integer,Integer> map=new HashMap<>();for (int i:nums){//遍历数组,如果i存在,取得存在的次数再+1,不存在,给一个默认值0 ,次数为0再+1;map.put(i, map.getOrDefault(i,0)+1);}//扫描map集合,将前k个最高频率放入优先级中Queue<Freq> queue=new PriorityQueue<>();for (Map.Entry<Integer,Integer>entry: map.entrySet()){if (queue.size()<k){queue.offer(new Freq(entry.getKey(),entry.getValue()));}else{//判断当前元素和堆顶元素次数大小。Freq freq=queue.peek();if (freq.times>entry.getValue()){continue;}else{queue.poll();queue.offer(new Freq(entry.getKey(),entry.getValue()));}}}for (int i=0;i<k;i++){ret[i]=queue.poll().key;}return ret;}

package ds.bin_tree.bin_tree_heap.leetcode;import java.util.*;/*** 查找和最小的k对数字* @Author liusifan* @Data 2022/3/11 17:23*/
public class Num373 {private class Pair{//第一个数组中的数int u;//第二个数组中的数int v;public Pair(int u, int v) {this.u = u;this.v = v;}}//前k个最小元素构建大根堆public List<List<Integer>> kSmallestPairs(int[] nums1, int[] nums2, int k) {PriorityQueue<Pair> queue=new PriorityQueue<>(new Comparator<Pair>() {@Overridepublic int compare(Pair o1, Pair o2) {return (o2.u+ o2.v)-(o1.u+o1.v);}});for (int i=0;i<Math.min(nums1.length,k);i++){for (int j=0;j<Math.min(nums2.length, k);j++){if (queue.size()<k){queue.offer(new Pair(nums1[i],nums2[j] ));}else{int add=nums1[i]+nums2[j];Pair pair=queue.peek();if (add>(pair.u+ pair.v)){continue;}else {queue.poll();queue.offer(new Pair(nums1[i],nums2[j] ));}}}}List<List<Integer>> ret=new ArrayList<>();//当k>数组长度的时候(例如有两个数对,k=3;)不可能出队三次,终止条件要加上!queue.isEmptyfor (int i = 0; i < k&&(!queue.isEmpty()); i++) {List<Integer> temp=new ArrayList<>();Pair pair=queue.poll();temp.add(pair.u);temp.add(pair.v);ret.add(temp);}Collections.reverse(ret);return ret;}
}

二叉堆(TopK问题,优先级队列)相关推荐

  1. 二叉堆详解实现优先级队列

    二叉堆详解实现优先级队列 文章目录 二叉堆详解实现优先级队列 一.二叉堆概览 二.优先级队列概览 三.实现 swim 和 sink 四.实现 delMax 和 insert 五.最后总结 二叉堆(Bi ...

  2. 《恋上数据结构第1季》二叉堆实现优先级队列

    优先级队列(Priority Queue) 优先级队列简介 优先队列的底层实现 二叉堆实现优先级队列源码 测试代码 数据结构与算法笔记目录:<恋上数据结构> 笔记目录 想加深 Java 基 ...

  3. Java PriorityQueue(优先级队列/二叉堆)的使用及题目应用

    目录 PriorityQueue有几个需要注意的点: 重写比较器的方法 应用题目 LeetCode 1845. 座位预约管理系统 LeetCode 215. 数组中的第 K 个最大元素(同剑指 Off ...

  4. 【数据结构与算法】二项队列与二叉堆的比较

    导语 二叉堆确实是入门级的重要数据结构了,而二项队列也是慢慢要去掌握的一种支持高效合并的优先队列实现.本文稍作比较,望抛砖引玉. 列个表格比较基本操作性能 基本操作 insert(平均) delete ...

  5. 优先队列与相关题目(Python、二叉堆)

    1. 优先队列知识 1.1 优先队列简介 优先队列:一种特殊的队列.在优先队列中,元素被赋予优先级,当访问队列元素时,具有最高优先级的元素最先删除. 优先队列与普通队列最大的不同点在于出队顺序 普通队 ...

  6. 排序算法之——优先队列经典实现(基于二叉堆)

    许多应用都需要处理有序的元素,但有时,我们不要求所有元素都有序,或是一定要一次就将它们排序,许多情况下,我们会收集这些元素里的最大值或最小值. 这种情况下一个合适的数据结构应该支持两种操作:插入元素. ...

  7. 二叉堆的优先队列基本原理及实现

    原理: 传统的队列是先进先出的数据结构,队列的重要变种称为优先级队列 二叉堆常见的遍体:最小堆(其中最小的键在前面)和最大堆(其中最大的键值总是在前面) 代码实现

  8. 数据结构之优先队列--二叉堆(Java实现)

    前言 数据结构队列的学习中,我们知道队列是先进先出的.任务被提交到队列中,按照先进先出的原则 对各个任务进行处理.不过在现实的情况下,任务通常有着优先级的概念,例如短任务.管理员的操作 应该优先执行. ...

  9. python优先队列的库,python优先队列及二叉堆的实现

    python优先队列及二叉堆的实现 发布于 2015-12-18 06:55:17 | 117 次阅读 | 评论: 0 | 来源: PHPERZ Python编程语言Python 是一种面向对象.解释 ...

最新文章

  1. Ovirt 安装部署方法
  2. ERICA:提升预训练语言模型实体与关系理解的统一框架
  3. 学习C++的五十个建议(转
  4. 苹果4s忘记id密码怎么办_苹果电脑 / Mac 忘记了开机密码怎么办?
  5. Adroid新增硬件编解码
  6. 在WinForm程序中嵌入ASP.NET[转]
  7. 与程序员朋友闲聊 通用权限管理系统有啥用?
  8. html弹跳qq群号代码,抖音上QQ群霸屏消息代码分享_抖音上QQ群霸屏消息代码大全-街机中国...
  9. c++和opencv小知识:openCV中convertTo的用法
  10. 知乎:前端IDE 那个流行,那个好;
  11. js实现签名功能(vue中使用电子签名)
  12. 将全部视频画面水平或者垂直翻转的实例教程分享
  13. 【问题征集】向 iPod 之父、iPhone 联合设计者、Google Nest 创始人 Tony Fadell 提问啦
  14. 如何开展业务是我在离开X网之后重新学的
  15. 画火柴人动画的手机软件_火柴人动漫制作软件下载-火柴人动漫制作手机中文版 v2.1.4_5577安卓网...
  16. 转:程序员应该怎样去学习和掌握计算机英语呢?
  17. 电脑怎么连接隐藏的无线WiFi信号呢?
  18. Numpy之数据归一化
  19. Windows10下利用Visual Studio Code搭建C语言开发环境
  20. 讲解基于verilog的4-2压缩器和3-2压缩器的实现方式,实现华莱士树(Wallace Tree)

热门文章

  1. 精品网址整理——计算机类学习视频资料
  2. 解决Mac下使用python绘图出现中文乱码的情况
  3. 第07章 图形操作 · 7.1 GDI原理(3)
  4. telnet测试http
  5. 驱动精灵2014网卡版 v8.0.515.1101 扩展版
  6. c语言队列渡船问题,渡船有关问题
  7. gh60(OK60RGB)刷固件折腾日志(MacOs版)
  8. CTF MICS笔记总结
  9. 全国与各省的2020年ESA10米土地利用镶嵌数据
  10. 联想笔记本安装PHP环境,联想笔记本装系统步骤 教你如何正确安装笔记本系统...