优先队列

头文件<queue>,优先队列的声明:template <typename T, typename Container=std::vector<T>, typename Compare=std::less<T>> class priority_queue,priority_queue第一个参数表示元素类型,第二个参数表示容纳参数的容器,默认是vector,第三个参数表示排序规则的断言,默认是less,从小到大。于是优先队列中的元素的队首元素是最大。

#include <queue>
#include <string>
#include <iostream>

using namespace std;

int main(){
	string wrds[]{"one","two","three","four"};
	priority_queue<string> words{begin(wrds),end(wrds)};
	cout<<words.top()<<endl;
	return 0;
}
打印“two”。

给出多个放在地平线上的矩形,矩形以x1、x2和h确定,矩形数组按照x1升序排序,返回这些矩形经过覆盖和遮挡后形成的背景的轮廓的关键点。[1]维护矩形高的最大堆que,将所有矩形的x1和x2合起来升序排序,x1和x2组成水平方向的分隔点,遍历矩形,若矩形x1小于或等于分隔点,把矩形的x2和高push到que中,若优先队列队首的x2小于等于分隔点,pop出que的队首元素。

用大小为k的滑动窗口从左到右找出nums窗口范围内的最大值。[2]
方法一:优先队列。用元素类型为pair<int,int>的优先队列,构建最大堆,pair的第一个元素表示nums[i],第二个元素表示i,获取最大堆的堆首的第一个元素为当前窗口的最大值,如果堆首的第二个元素不在当前滑动窗口范围内,pop堆首。时间复杂度O(nlogn),拿每个元素建堆的时间复杂度O(logn),n个元素;空间复杂度O(n),堆的大小。
方法二:单调队列。维持以当前元素为结尾的递减双向队列,双向队列里存储元素的索引值,双向队列的首索引对应的元素即是最大值,注意索引不要在滑动窗口外面。时间复杂度O(n),遍历一遍nums的元素;空间复杂度O(k),双向队列的最大长度为滑动窗口长度。
方法三:分块。设i是k的倍数,以[i,i+k-1]为一个块。滑动窗口也是长度为k的块,若滑动窗口与[i,i+k-1]重合,我们若预先得到这个标准块的最大值,那结果呼之欲出,但滑动窗口不与标准块重合,设滑动窗口起点j满足j<i<j+k-1,则滑动窗口的最大值取[j,i)和[i,j+k-1]两段子段的最大值的最大值。根据以上数学推理,构造prefix[0:n],suffix[0:n],prefix[i]表示i所在的标准块中以i为结尾的前缀子段的最大值,suffix[i]表示i所在的标准块中以i开始的后缀子段的最大值。当i%k==0时,prefix[i]=nums[i],否则prefix[i]=max(prefix[i-1],nums[i]);当(i+1)%k==0(表示i是标准块的最后一个元素的索引)或i==n-1(最后一个标准块的最后一个元素的索引是n-1)时,suffix[i]=nums[i],否则suffix[i]=max(suffix[i+1],nums[i])。当滑动窗口不与标准块重合时,res.emplace_back(max(suffix[i],prefix[i+k-1])),i表示滑动窗口的起点,若滑动窗口与标准块重合,suffix[i]==prefix[i+k-1],为标准块的最大值。时间复杂度和空间复杂度O(n)。

[start,end]表示会议的开始时间和结束时间,问最少准备多少间会议室使得所有会议不冲突地被举行。[3]构建最小堆,排序会议时间表,进入一个会议开始时间,把最小堆里小于等于该开始时间的时间排出去,插入会议结束时间,获取此时最小堆的size的最大值,即为结果。

参考链接:[1].218. 天际线问题
[2].239. 滑动窗口最大值
[3].253. 会议室 II

创建于2022.4.24/11.53,修改于2022.9.8/11.39

#priority-queue