栈与队列part01
day42-1 ● 理论基础
队列:先入先出
栈:先进后出
day42-2 ● 232.用栈实现队列
整体思路
栈实现队列:入栈+出栈
代码实现
class MyQueue {
/**
* 时间复杂度: push和empty为O(1), pop和peek为O(n)
* 空间复杂度: O(n)
*/
Stack<Integer> stackIn;
Stack<Integer> stackOut;
/**
* Initialize your data structure here.
*/
public MyQueue() {
stackIn = new Stack<>();
stackOut = new Stack<>();
}
/**
* Push element x to the back of queue.
*/
public void push(int x) {
stackIn.push(x);
}
/**
* Removes the element from in front of queue and returns that element.
*/
public int pop() {
dumpStackIn();
return stackOut.pop();
}
/**
* Get the front element.
*/
public int peek() {
dumpStackIn();
return stackOut.peek();
}
/**
* Returns whether the queue is empty.
*/
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
// 如果stackOut为空,将stackIn中的元素全部放到stackOut中
private void dumpStackIn() {
if (!stackOut.isEmpty()) return;
while (!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
}
}
/**
* 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();
*/
总结
复用思想
函数复用很重要
day42-3 ● 225. 用队列实现栈
整体思路
一个队列就可以实现栈了
两个队列实现栈:没有输入输出(栈实现队列)的关系,而另一个队列完全用于备份
代码实现
class MyStack {
Queue<Integer> queue;
public MyStack() {
queue = new LinkedList<>();
}
public void push(int x) {
queue.offer(x);
}
public int pop() {
rePosition();
return queue.poll();
}
public int top() {
rePosition();
int result = queue.poll();
queue.offer(result);
return result;
}
public boolean empty() {
return queue.isEmpty();
}
public void rePosition() {
int size = queue.size();
size--;
while (size-- > 0) {
queue.add(queue.poll());
}
}
}
/**
* 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();
*/
总结
节约资源
方法尽量复用
day42-4 ● 20. 有效的括号
整体思路
栈在计算机系统中的应用场景:编译器做词法分析、Linux的命令进哪一个目录
栈模拟三种不匹配的情况
不匹配的三种情况:
第一种情况,字符串里左方向的括号多余了 ,所以不匹配
第二种情况,括号没有多余,但是 括号的类型没有匹配上
第三种情况,字符串里右方向的括号多余了,所以不匹配。
代码实现
class Solution {
public boolean isValid(String s) {
Deque<Character> deque = new LinkedList<>();
char ch;
for (int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
// 碰到左括号,就把相应的右括号入栈
if (ch == '(') {
deque.push(')');
} else if (ch == '{') {
deque.push('}');
} else if (ch == '[') {
deque.push(']');
} else if (deque.isEmpty() || deque.peek() != ch) {
return false;
}else {// 如果是右括号判断是否和栈顶元素匹配
deque.pop();
}
}
// 最后判断栈中元素是否为空
return deque.isEmpty();
}
}
总结
第一种情况是在遍历完之后处理的
day42-1 ● 1047. 删除字符串中的所有相邻重复项
整体思路
栈实现
代码实现
class Solution {
// 使用 Deque 作为堆栈
public String removeDuplicates(String s) {
// ArrayDeque会比LinkedList在除了删除元素这一点外会快一点
ArrayDeque<Character> deque = new ArrayDeque<>();
char ch;
for (int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
if (deque.isEmpty() || deque.peek() != ch) {
deque.push(ch);
} else {
deque.pop();
}
}
// //剩余的元素即为不重复的元素
String str = "";
while (!deque.isEmpty()) {
str = deque.pop() + str;
}
return str;
}
// 拿字符串直接作为栈,省去了栈还要转为字符串的操作。
// 拓展:双指针
}
总结
开心消消乐