Leetcode---10.优先队列篇
基本概念:
队列是一种特殊的线性表。以一个普通的单端队列为例,只允许在表的前端进行删除操作,而在表的后端进行插入操作。队列的入和出与元素(数据)进的次序有关,只有最早进入队列的元素才能最先从队列中删除,所以队列又被称为先进先出(FIFO—first in first out)线性表。
优先队列和队列有什么区别?优先队列的入和出与元素(数据)进的次序无关,而是由设定的优先级来决定元素的弹出次序,优先级最高的元素最先得到服务,优先级相同的元素按照其在优先队列中的顺序得到服务。在生活中,我们处理任务的时候总是会给任务区分优先级,首先我们会处理优先级高的任务,接着我们会处理下一个优先级较高的任务,这其实就是一个优先队列。例如乘客排队登机,一般情况下排在前面的人员先登机,若队列中有老人、孩子,可以排列到最前面先登机。
实现原理:
实现优先队列的方式有多种,如数组、链表、平衡二叉树(如:AVL树和RB树)、堆等。
我们以堆来说明一下优先队列的实现原理。堆是一种完全二叉树,可以分为小顶堆和大顶堆。小顶堆指的是堆顶元素(即树的根节点)为堆中最小值,且每一个节点的值都必须 小于等于 其孩子节点的值;反之即大顶堆。如下图:
对堆的操作主要有两个,即插入或删除,且都是在顶端进行。由于堆是一个完全二叉树,删除和添加后都需要保证是完全二叉树,一般情况是先和最后一个节点进行交换,然后再进行删除和添加。
以左边小顶堆删除堆顶节点1的操作为例,堆顶节点1先和最后一个节点7进行交换,然后删除1,节点7到了堆顶;这时还要保证每一个节点的值都必须 小于等于 其孩子节点的值,所以节点7和它的左右子树比较,找到其中较小的进行交换,然后一直交换到叶子节点。如下:
插入操作类似上面。由于堆是一个完全二叉树,它的操作时间复杂度一般都能达到O(logN)。
堆的实现原理和样例可以参考https://leetcode-cn.com/leetbook/read/heap/enhu1g/、http://3ms.huawei.com/hi/group/913/thread_8177086.html?mapId=9985980&for_statistic_from=all_group_forum
使用场景:
优先队列适用于动态维持有序状态的场景,可以提高排序效率,有以下几种应用:
1)任务调度:先处理高优先级的任务,再处理普通任务;可增加新的任务到优先队列中,并按照优先级排序。
2)Top K问题:找到满足要求的前K个元素
练习题:
621. 任务调度器
https://leetcode-cn.com/problems/task-scheduler/
253. 会议室 II
https://leetcode-cn.com/problems/meeting-rooms-ii/
703. 数据流中的第 K 大元素
https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/
347. 前 K 个高频元素
https://leetcode-cn.com/problems/top-k-frequent-elements/
215. 数组中的第K个最大元素
https://leetcode-cn.com/problems/kth-largest-element-in-an-array/
剑指 Offer II 061. 和最小的 k 个数对
https://leetcode-cn.com/problems/qn8gGX/