普通的双端队列
用栈实现队列
java
import java.util.ArrayDeque;
import java.util.Deque;
class MyQueue {
// 使用双端队列(Deque)来实现一个队列
Deque<Integer> input; // 用于存放新加入的元素
Deque<Integer> output; // 用于存放准备出队的元素
public MyQueue() {
input = new ArrayDeque<>(); // 初始化input队列
output = new ArrayDeque<>(); // 初始化output队列
}
public void push(int x) {
// 将元素x添加到input队列的前端
input.addFirst(x);
}
public int pop() {
// 首先调用exchange方法,确保output队列中有元素
exchange();
// 从output队列的前端移除并返回元素
return output.removeFirst();
}
public int peek() {
// 首先调用exchange方法,确保output队列中有元素
exchange();
// 返回output队列前端的元素,但不移除它
return output.getFirst();
}
public boolean empty() {
// 如果input和output队列都为空,则返回true,表示队列为空
return input.isEmpty() && output.isEmpty();
}
public void exchange() {
// 如果output队列不为空,则不需要交换,直接返回
if (!output.isEmpty()) {
return;
}
// 当output队列为空时,将input队列中的所有元素转移到output队列
while (!input.isEmpty()) {
int temp = input.removeFirst(); // 从input队列前端移除元素
output.addFirst(temp); // 将移除的元素添加到output队列的前端
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue(); // 创建MyQueue对象
* obj.push(x); // 将元素x添加到队列
* int param_2 = obj.pop(); // 移除并返回队列前端的元素
* int param_3 = obj.peek(); // 返回队列前端的元素,但不移除
* boolean param_4 = obj.empty(); // 检查队列是否为空
*/
有效的括号(难)
java
import java.util.ArrayDeque;
import java.util.Deque;
class Solution {
public boolean isValid(String s) {
// 使用双端队列(Deque)来存储尚未匹配的右括号
Deque<Character> deque = new ArrayDeque<>();
// 遍历字符串s中的每个字符
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i); // 获取当前遍历到的字符
// 如果当前字符是左括号,将其对应的右括号添加到队列的前端
if (ch == '(') {
deque.addFirst(')');
} else if (ch == '{') {
deque.addFirst('}');
} else if (ch == '[') {
deque.addFirst(']');
} else {
// 如果当前字符是右括号
// 检查栈是否为空或者栈顶元素是否与当前右括号匹配
if (deque.isEmpty() || ch != deque.getFirst()) {
// 如果栈为空或者栈顶元素不匹配,说明括号序列无效,返回false
return false;
} else {
// 如果栈顶元素与当前右括号匹配,从队列中移除栈顶元素
deque.removeFirst();
}
}
}
// 最后检查栈是否为空,如果为空,说明所有括号都正确匹配,返回true;否则返回false
return deque.isEmpty();
}
}
删除字符串中的所有相邻重复项
1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
java
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.StringBuilder;
class Solution {
public String removeDuplicates(String s) {
// 使用双端队列(Deque)来存储不重复的字符
Deque<Character> deque = new ArrayDeque<>();
// 遍历字符串s中的每个字符
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i); // 获取当前遍历到的字符
// 如果队列不为空且队列的第一个字符与当前字符相同
if (!deque.isEmpty() && deque.getFirst() == ch) {
// 移除队列中的第一个字符
deque.removeFirst();
} else {
// 否则,将当前字符添加到队列的前端
deque.addFirst(ch);
}
}
// 使用StringBuilder来构建最终的字符串
StringBuilder sb = new StringBuilder();
// 遍历队列,将队列中的字符添加到StringBuilder中
while (!deque.isEmpty()) {
sb.append(deque.removeLast()); // 从队列的后端移除字符并添加到StringBuilder
}
// 将StringBuilder转换为字符串并返回
return sb.toString();
}
}
逆波兰表达式求值
java
import java.util.ArrayDeque;
import java.util.Deque;
class Solution {
public int evalRPN(String[] tokens) {
// 使用双端队列(Deque)来存储操作数
Deque<Integer> deque = new ArrayDeque<>();
// 遍历tokens数组中的每个元素
for (int i = 0; i < tokens.length; i++) {
String ch = tokens[i]; // 获取当前遍历到的元素
// 如果当前元素是运算符
if (ch.equals("+")) {
// 从队列中弹出前两个操作数
int first = deque.removeFirst();
int second = deque.removeFirst();
// 计算它们的和,并将其压入队列前端
int sum = first + second;
deque.addFirst(sum);
} else if (ch.equals("-")) {
// 从队列中弹出前两个操作数
int first = deque.removeFirst();
int second = deque.removeFirst();
// 计算它们的差,并将其压入队列前端
int sum = second - first;
deque.addFirst(sum);
} else if (ch.equals("*")) {
// 从队列中弹出前两个操作数
int first = deque.removeFirst();
int second = deque.removeFirst();
// 计算它们的乘积,并将其压入队列前端
int sum = first * second;
deque.addFirst(sum);
} else if (ch.equals("/")) {
// 从队列中弹出前两个操作数
int first = deque.removeFirst();
int second = deque.removeFirst();
// 计算它们的商,并将其压入队列前端
// 注意:这里假设不会出现除以零的情况
int sum = second / first;
deque.addFirst(sum);
} else {
// 如果当前元素不是运算符,将其转换为整数并压入队列前端
deque.addFirst(Integer.parseInt(ch));
}
}
// 返回队列中的第一个元素,即表达式的结果
return deque.getFirst();
}
}
单调队列
滑动窗口最大值(难)
java
import java.util.ArrayDeque;
import java.util.Deque;
class MyDeque {
Deque<Integer> deque; // 双端队列,用于存储元素
MyDeque() {
deque = new ArrayDeque<>(); // 初始化双端队列
}
// 尝试移除队列头部的元素,如果头部元素等于val
boolean remove(int val) {
if (!deque.isEmpty() && deque.getFirst() == val) {
deque.removeFirst(); // 移除队列头部元素
}
return true; // 无论是否移除,都返回true
}
// 将val添加到队列中,移除所有比val小的尾部元素
boolean add(int val) {
while (!deque.isEmpty() && deque.getLast() < val) {
deque.removeLast(); // 移除队列尾部元素
}
deque.addLast(val); // 添加val到队列尾部
return true; // 返回true表示添加成功
}
// 返回队列头部的元素,即当前窗口中的最大值
int maxValue() {
return deque.getFirst(); // 返回队列头部元素
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length; // 输入数组的长度
int[] ret = new int[n - k + 1]; // 存储每个窗口的最大值
MyDeque deque = new MyDeque(); // 创建MyDeque对象
// 将数组的前k个元素添加到队列中
for (int i = 0; i < k; i++) {
deque.add(nums[i]);
}
// 将第一个窗口的最大值添加到结果数组中
int index = 0;
ret[index++] = deque.maxValue();
// 遍历数组,从索引k到n-1
for (int i = k; i < n; i++) {
// 移除窗口外的元素
deque.remove(nums[i - k]);
// 将当前元素添加到队列中
deque.add(nums[i]);
// 将当前窗口的最大值添加到结果数组中
ret[index++] = deque.maxValue();
}
return ret; // 返回结果数组
}
}
优先队列
前 K 个高频元素(难)
java
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 创建一个HashMap来存储数组中每个数字的出现次数
HashMap<Integer, Integer> hashmap = new HashMap<>();
for (int num : nums) {
// 对于数组中的每个数字,如果它已经在HashMap中,则增加其计数,否则添加到HashMap中并设置计数为1
hashmap.put(num, hashmap.getOrDefault(num, 0) + 1);
}
// 创建一个小顶堆(PriorityQueue),用于存储二元组(数字,出现次数)
// 比较器使用Lambda表达式,根据二元组的第二个元素(出现次数)来比较
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1] - pair2[1]);
for (Map.Entry<Integer, Integer> entry : hashmap.entrySet()) {
// 遍历HashMap中的每个条目
if (pq.size() < k) {
// 如果堆的大小小于k,则直接添加当前条目
pq.add(new int[]{entry.getKey(), entry.getValue()});
} else {
// 如果堆的大小已经达到k,并且堆顶元素的出现次数小于当前条目的出现次数
if (pq.peek()[1] < entry.getValue()) {
// 移除堆顶元素(出现次数最小的元素)
pq.poll();
// 添加当前条目
pq.add(new int[]{entry.getKey(), entry.getValue()});
}
}
}
// 创建一个数组来存储最终的k个最频繁出现的数字
int[] ret = new int[k];
for (int i = 0; i < k; i++) {
// 依次从堆中取出元素,填充到数组中
ret[i] = pq.poll()[0];
}
// 返回结果数组
return ret;
}
}