[TOC]
本文主要介绍数据结构算法中中常见的面试高频知识点:优先级队列(priority-queue)。如果您之前学习过本文的堆排序后,那本质上对优先级队列的底层实现也就非常了解了。本文不会讲解优先级队列的底层实现,只会关注于其使用和相关的题目。
熟练本文的优先级队列的代码后您将至少可以解决以下Leetcode题目:
题目序号 | 相关链接 | 备注 |
---|---|---|
622. 设计循环队列(中等难度) | 622. 设计循环队列 - 力扣(LeetCode) (leetcode-cn.com) | 注意队首指针和队尾指针的定义 |
641. 设计循环双端队列(中等难度) | 641. 设计循环双端队列 - 力扣(LeetCode) (leetcode-cn.com) | 注意队首指针和队尾指针的定义 |
1670. 设计前中后队列(中等难度) | 1670. 设计前中后队列 - 力扣(LeetCode) (leetcode-cn.com) | |
剑指 Offer 59 - II. 队列的最大值(中等难度) | 剑指 Offer 59 - II. 队列的最大值 - 力扣(LeetCode) (leetcode-cn.com) |
一、循环队列的相关LeetCode题目解析
【first队首指针】指向队列头部第 11 个有效数据的位置;
【last队尾指针】指向队列尾部的下一个位置,即下一个从队尾入队元素的位置。
即使是循环双端队列,这种定义也不变。
1、设计循环队列
622. 设计循环队列 - 力扣(LeetCode) (leetcode-cn.com)
2、设计循环双端队列
641. 设计循环双端队列 - 力扣(LeetCode) (leetcode-cn.com)
3、设计前中后队列
1670. 设计前中后队列 - 力扣(LeetCode) (leetcode-cn.com)
4、设计最大值队列
剑指 Offer 59 - II. 队列的最大值 - 力扣(LeetCode) (leetcode-cn.com)
本题的解题思路:定义一个普通队列queue用于正常出入队,一个双端队列deque用于存放最大元素。
比如,连续放入三个元素1,2,3,那么queue里面就是1,2,3,,但是deque只存最大值3在队头
再比如1,2,3,4,5,4,1,2,3
按照这个顺序入队,那么deque只需存放5,4,3
二、LeetCode题目答案
本小节直接给出本文各个题目的答案,供有需求的读者复制。
1、622. 设计循环队列(中等难度)
class MyCircularQueue {
private:
int mCapacity;
int mSize;
int * array;
int first;
int last;
public:
MyCircularQueue(int k) {
mCapacity=k;
array=new int[mCapacity];
first=0;
last=0;
mSize=0;
}
~MyCircularQueue() {
delete [] array;
}
// 入队
bool enQueue(int value) {
if(isFull()) return false;
if(last==mCapacity-1){
array[last]=value;
last=0;
}
else{
array[last++]=value;
}
mSize++;
return true;
}
// 出队
bool deQueue() {
if(isEmpty()) return false;
if(first==mCapacity-1){
first=0;
}else{
first++;
}
mSize--;
return true;
}
int Front() {
if(isEmpty()) return -1;
return array[first];
}
int Rear() {
if(isEmpty()) return -1;
if(last==0) return array[mCapacity-1];
return array[last-1];
}
bool isEmpty() {
if(mSize==0) return true;
return false;
}
bool isFull() {
if(mSize==mCapacity)return true;
return false;
}
};
2、641. 设计循环双端队列(中等难度)
class MyCircularDeque {
private:
int mSize;
int mCapacity;
int first;
int last;
int * array;
public:
MyCircularDeque(int k) {
mCapacity=k;
array=new int[mCapacity];
mSize=0;
first=0;
last=0;
}
~MyCircularDeque() {
delete [] array;
}
//入队首
bool insertFront(int value) {
if(isFull()) return false;
if(first==0){
first=mCapacity-1;
array[first]=value;
}else{
first--;
array[first]=value;
}
mSize++;
return true;
}
//入队尾
bool insertLast(int value) {
if(isFull()) return false;
if(last==mCapacity-1){
array[last]=value;
last=0;
}else{
array[last]=value;
last++;
}
mSize++;
return true;
}
//出队首
bool deleteFront() {
if(isEmpty()) return false;
if(first==mCapacity-1) first=0;
else first++;
mSize--;
return true;
}
//出队尾
bool deleteLast() {
if(isEmpty()) return false;
if(last==0) last=mCapacity-1;
else last--;
mSize--;
return true;
}
int getFront() {
if(isEmpty()) return -1;
else return array[first];
}
int getRear() {
if(isEmpty()) return -1;
if(last==0) return array[mCapacity-1];
else return array[last-1];
}
bool isEmpty() {
if(mSize==0) return true;
return false;
}
bool isFull() {
if(mSize==mCapacity) return true;
return false;
}
};
3、1670. 设计前中后队列(中等难度)
class FrontMiddleBackQueue {
private:
vector<int> array;// 数组
public:
FrontMiddleBackQueue() {
}
void pushFront(int val) {
array.insert(array.begin(),val);
}
void pushMiddle(int val) {
int len=array.size();
int mid=len/2;
array.insert(array.begin()+mid,val);
}
void pushBack(int val) {
array.push_back(val);
}
int popFront() {
if (array.empty()) {
return -1;
}
int res=array.front();
array.erase(array.begin());
return res;
}
int popMiddle() {
if (array.empty()) {
return -1;
}
int len=array.size();
int mid=(len-1)/2;
int res=array[mid];
array.erase(array.begin()+mid);
return res;
}
int popBack() {
if (array.empty()) {
return -1;
}
int res=array.back();
array.pop_back();
return res;
}
};
4、剑指 Offer 59 - II. 队列的最大值(中等难度)
class MaxQueue {
private:
queue<int> que; // 普通队列
deque<int> deq; // 双端队列
public:
MaxQueue() {}
// 获取最大值
int max_value() {
if(que.empty()) return -1;
return deq.front();
}
// 入队
void push_back(int value) {
que.push(value);//普通队列入队
//加入双端队列之前,将其中小于value的值都弹出
while(!deq.empty()&&deq.back()<value)
deq.pop_back();
deq.push_back(value);//双端队列入队
}
// 出队
int pop_front() {
if(que.empty()) return -1;
// 普通队列弹出一个元素
int a=que.front();
que.pop();
// 如果双端队列的队首元素和当前弹出的元素相等,则一起弹出
if(a==deq.front())
deq.pop_front();
return a;
}
};