Queue & Deque学习
学习链接 link.
Queue
Java 集合中的 Queue 继承自 Collection 接口。
Queue是java中实现队列的接口,Queue的实现类有LinkedList和PriorityQueue。最常用的实现类是LinkedList。
Queue<Object> queue = new LinkedList();
Queue的6个方法:
Queue是一个先进先出的队列。
-
压入元素(添加):add()、offer()
相同:未超出容量,从队尾压入元素,返回压入的那个元素。
区别:在超出容量时,add()方法会对抛出异常,offer()返回false -
弹出元素(删除):remove()、poll()
相同:容量大于0的时候,删除并返回队头被删除的那个元素。
区别:在容量为0的时候,remove()会抛出异常,poll()返回false -
获取队头元素(不删除):element()、peek()
相同:容量大于0的时候,都返回队头元素。但是不删除。
区别:容量为0的时候,element()会抛出异常,peek()返回null。
Deque
Deque是一个双端队列接口,继承自Queue接口,Deque的实现类是LinkedList、ArrayDeque、LinkedBlockingDeque,其中LinkedList是最常用的。
Deque有三种用途:
普通队列(一端进另一端出):
Queue queue = new LinkedList()或Deque deque = new LinkedList()
双端队列(两端都可进出)
Deque deque = new LinkedList()
堆栈
Deque deque = new LinkedList()
十二种方法:
双端队列也可用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留 Stack 类。在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于 Deque 方法,如下表所示:
20. 有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
public boolean isValid(String s) {
Deque<Character> stack = new LinkedList<>();
char[] chars = s.toCharArray();
for (char c : chars) {
if (c == '(') {
stack.push(')');
} else if (c == '[') {
stack.push(']');
} else if (c == '{') {
stack.push('}');
} else if (!stack.isEmpty() && stack.peek().equals(c)) {
stack.pop();
} else {
return false;
}
}
return stack.isEmpty();
}
1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
public String removeDuplicates(String s) {
Deque<Character> stack = new LinkedList<>();
char[] chars = s.toCharArray();
for (char c : chars) {
if(stack.isEmpty()){
stack.push(c);
continue;
}
if(!stack.isEmpty()){
if(stack.peek().equals(c)){
stack.pop();
}else {
stack.push(c);
}
}
}
StringBuilder sb = new StringBuilder();
while(!stack.isEmpty()){
sb.append(stack.pollLast());
}
return sb.toString();
}
150. 逆波兰表达式求值
根据 逆波兰表示法,求表达式的值。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
import java.util.Deque;
import java.util.LinkedList;
class Solution {
public int evalRPN(String[] tokens) {
Deque<String> stack= new LinkedList<>();
for (String token : tokens) {
if(!isOp(token)){
stack.push(token);
continue;
}
if(token.equals("+")){
String s = stack.pop();
String s1 = stack.pop();
int i = Integer.valueOf(s) + Integer.valueOf(s1);
stack.push(Integer.toString(i));
continue;
}
if(token.equals("-")){
String s = stack.pop();
String s1 = stack.pop();
int i = Integer.valueOf(s1) - Integer.valueOf(s);
stack.push(Integer.toString(i));
continue;
}
if(token.equals("*")){
String s = stack.pop();
String s1 = stack.pop();
int i = Integer.valueOf(s) * Integer.valueOf(s1);
stack.push(Integer.toString(i));
continue;
}
if(token.equals("/")){
String s = stack.pop();
String s1 = stack.pop();
int i = Integer.valueOf(s1) / Integer.valueOf(s);
stack.push(Integer.toString(i));
continue;
}
}
return Integer.valueOf(stack.pop());
}
public boolean isOp(String s){
return s.equals("+") || s.equals("-") ||s.equals("*") ||s.equals("/");
}
}
347. 前 K 个高频元素
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
public int[] topKFrequent(int[] nums, int k) {
//map记录每个数字出现的频率
HashMap<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num,map.getOrDefault(num,0)+1);
}
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
//new一个优先队列(内部原理与堆一样)
//用lambda表达式设置成小顶堆的排序方式
PriorityQueue<Map.Entry<Integer, Integer>> queue =
new PriorityQueue<>((o1,o2)->o1.getValue()-o2.getValue());
//加入队列中
for (Map.Entry<Integer, Integer> entry : entries) {
queue.offer(entry);
//只保存我们需要的k个 其他的弹出
if(queue.size()>k){
queue.poll();
}
}
int[] result = new int[k];
for (int i = k - 1; i >= 0; i--) {
result[i] = queue.poll().getKey();
}
return result;
}