关于队列和栈的算法总结
栈(Stack)是限定仅在表尾进行插入和删除操作的线性列表
我们把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈,栈又称后进先出的线性表
队列是只允许在一段插入,而在另一端进行删除操作的线性表,
队列是一种先进先出的线性表,允许插入的一段称为队尾,允许删除的一段称为队头
函数
stack
修饰符类型 | 方法 |
---|---|
boolean | empty() 测试栈是否为空 |
E | peek() 在不将其从栈中移除的情况下,查看该栈顶部的对象。在栈为空的时候会报EmptyStackException |
E | pop() 删除此栈顶部的对象,并将该对象作为此函数的值返回。在栈为空的时候会报EmptyStackException |
E | push(E item) 将一个项目推送到此堆栈的顶部。 |
int | search(Object o) 返回对象在此栈上的从1开始的位置。对象不存在则会返回-1 |
Queue
修饰符类型 | 方法 |
---|---|
boolean | add(E e) 如果可以立即将指定的元素插入此队列,而不会违反容量限制,则在成功时返回true,如果当前没有可用空间,则抛出IllegalStateException。 |
E | element() 检索但不删除此队列的头。如果队列为空抛出NoSuchElementException |
boolean | offer(E e) 如果可以在不违反容量限制的情况下立即将指定的元素插入此队列。 |
E | peek() 检索但不删除此队列的头部,如果此队列为空,则返回null。 |
E | poll() 检索并删除此队列的头部,如果此队列为空,则返回null。 |
E | remove() 检索并删除此队列的头,如果队列为空抛出NoSuchElementException |
抛出异常 | 返回booleam值 | |
---|---|---|
Insert | add(e) | offer(e) |
Remove | remove() | poll() |
Examine | element() | peek() |
Deque(双向队列)
功能 | 队头开始 | 队尾开始 |
---|---|---|
添加元素,超出抛出IllegalStateException | void addFirst(E e) | void addLast(E e) |
添加元素,超出返回false | boolean offerFirst(E e) | boolean offerLast(E e) |
移除元素并返回,如果队列为空抛出NoSuchElementException | E removeFirst() | E removeLast() |
移除元素并返回,如果队列为空返回null | E pollFirst() | E pollLast() |
获得元素,但是不删除,如果队列为空抛出NoSuchElementException | E getFirst() | E getLast() |
返回元素,但是不删除,如果队列为空返回null | E peekFirst() | E peekLast() |
删除第一个相同元素,依次检索 | boolean removeFirstOccurrence(Object o) | boolean removeLastOccurrence(Object o) |
ArrayDeque
ArrayDeque当用作栈时,此类可能比 Stack 快,而用作队列时,则比 LinkedList 要快。
Leetcode
232. 用栈实现队列 - 力扣(LeetCode) (leetcode-cn.com)
class MyQueue {
Stack<Integer> stackIn;
Stack<Integer> stackOut;
public MyQueue() {
stackIn = new Stack();
stackOut = new Stack();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
if(!stackOut.isEmpty()) return stackOut.pop();
while(!stackIn.isEmpty()) stackOut.push(stackIn.pop());
return stackOut.pop();
}
public int peek() {
if(!stackOut.isEmpty()) return stackOut.peek();
while(!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty() &&stackOut.isEmpty();
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
225. 用队列实现栈 - 力扣(LeetCode) (leetcode-cn.com)
class MyStack {
Queue<Integer> queue1;
Queue<Integer> queue2;
public MyStack() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
public void push(int x) {
queue2.offer(x);
while(!queue1.isEmpty()){
queue2.offer(queue1.poll());
}
Queue temp = queue1;
queue1 = queue2;
queue2 = temp;
}
public int pop() {
return queue1.poll();
}
public int top() {
return queue1.peek();
}
public boolean empty() {
return queue1.isEmpty();
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
20. 有效的括号 - 力扣(LeetCode) (leetcode-cn.com)
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(char c : s.toCharArray()){
if(c == '(') stack.push(')');
else if(c == '[') stack.push(']');
else if(c == '{') stack.push('}');
else if(stack.isEmpty() || c!=stack.pop()) return false;
}
return stack.isEmpty();
}
}
1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode) (leetcode-cn.com)
遇到相同的元素弹栈
class Solution {
public String removeDuplicates(String s) {
ArrayDeque<Character> queue = new ArrayDeque<>();
for(char c : s.toCharArray()){
if(queue.isEmpty() || c != queue.peek()) queue.push(c);
else queue.pop();
}
String ss = "";
while(!queue.isEmpty()){
ss = queue.pop() + ss;
}
return ss;
}
}
150. 逆波兰表达式求值 - 力扣(LeetCode) (leetcode-cn.com)
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> deque = new LinkedList();//存在数字
for(String s : tokens){
if(s.equals("+")) deque.push(deque.pop() + deque.pop());
else if(s.equals("-")) deque.push(-deque.pop() + deque.pop());
else if(s.equals("*")) deque.push(deque.pop() * deque.pop());
else if(s.equals("/")){
int temp = deque.pop();
int temp2 = deque.pop();
deque.push(temp2/temp);
}else{
deque.push(Integer.valueOf(s));
}
}
return deque.pop();
}
}
239. 滑动窗口最大值 - 力扣(LeetCode) (leetcode-cn.com)
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//创建一个存放下标的栈
ArrayDeque<Integer> deque = new ArrayDeque<>();
int[] res = new int[nums.length - k +1];
for(int i = 0;i < nums.length;i++){
//头节点的下标不在范围内,弹出
while(!deque.isEmpty() && deque.peek() < (i-k+1)) deque.poll();
//加入的元素大于末尾的元素,末尾的元素弹出
while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) deque.pollLast();
deque.offer(i);
if(i+1 >= k) res[i-k+1] = nums[deque.peek()];
}
return res;
}
}
347. 前 K 个高频元素 - 力扣(LeetCode) (leetcode-cn.com)
class Solution {
public int[] topKFrequent(int[] nums, int k) {
//构建一个结果集合
int[] res = new int[k];
//map集合
Map<Integer,Integer> map = new HashMap<>();
for(int num : nums){
map.put(num,map.getOrDefault(num,0)+1);
}
Set<Map.Entry<Integer,Integer>> entry = map.entrySet();
PriorityQueue<Map.Entry<Integer,Integer>> pq = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue());
for(Map.Entry<Integer,Integer> e : entry){
pq.offer(e);
if(pq.size() > k)pq.poll();
}
for(int i = k-1;i>=0 ;i --){
res[i] = pq.poll().getKey();
}
return res;
}
}