栈与队列基础
- 栈(stack):先进后出(LIFO),常见操作有
push()
、pop()
、peek()
、isEmpty()
- 队列(queue):先进先出(FIFO),常见操作有
offer()
/add()
、poll()
/remove()
、peek()
、isEmpty()
栈和队列的操作的时间复杂度一般是O(1)
LeetCode - 232. Implement Queue using Stacks 用栈实现队列
解题目标:用栈来实现一个FIFO队列
解题思路:用两个栈来模拟队列,先把所有元素入栈stackIn,再依次出栈放到另一个stackOut栈中。stackIn相当于一个暂存区,关键是出栈的逻辑,假如stackOut的元素还没出完是不能添加进去的,否则顺序就乱了,必须先判断stackOut是否为空才能从stackIn出栈再全部加入。比如下面这个例子一次性加入元素1,2,3,使用pop()后stackOut依然残留元素2,3。这个时候假如push(4),stackIn就不能直接添加到stackOut了。
注意事项:必须要等stackOut全部出栈之后才能让stackIn出栈的元素进栈到stackOut。
class MyQueue {
//we need two stacks here
Stack<Integer> stackIn;
Stack<Integer> stackOut;
public MyQueue() {
// initialize two stacks
stackIn = new Stack<>();
stackOut = new Stack<>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
if (stackOut.isEmpty()) {
while (!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
}
return stackOut.pop();
}
public int peek() {
if (stackOut.isEmpty()) {
while (!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
}
return stackOut.peek();
}
public boolean empty() {
return stackOut.isEmpty() && stackIn.isEmpty();
}
}
LeetCode - 225. Implement Stack using Queues 用队列实现栈
解题思路:这题可以只用一个队列来达到目的,在pop的时候得到的是栈的顶层元素,但在队列中就相当于弹出队列中最后一个元素,队列中能够弹出的也只能是头一个元素,因此每一次push就把第1~n-1个元素重新排列进队列即可。
class MyStack {
Queue<Integer> q;
public MyStack() {
q = new LinkedList<>();
}
public void push(int x) {
q.add(x);
//每次添加都把前面的元素全部重新进入队列
int queueSize = q.size();
while (queueSize-- > 1) {
q.add(q.poll());
}
}
public int pop() {
return q.poll();
}
public int top() {
return q.peek();
}
public boolean empty() {
return q.isEmpty();
}
}
LeetCode - 20. Valid Parentheses 有效的括号
解题目标:检查字符串中的括号等类似符号是否正确闭合
解题思路:在碰到左符号时,在栈中加入右符号,碰到右符号就和栈顶元素进行比对。注意必须是遍历完成后stack刚好为空才证明匹配成功,中途就空了说明右符号多了。
import java.nio.charset.Charset;class Solution {
public boolean isValid(String s) {
Stack<Character> charStack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '[' || c == '(' || c == '{') {
if (c == '[' ) {
charStack.add(']');
} else if (c == '(') {
charStack.add(')');
} else {
charStack.add('}');
}
} else {
if (charStack.isEmpty()) {
return false;
} else {
if (c == charStack.peek()) {
charStack.pop();
} else {
return false;
}
}
}
}
return charStack.isEmpty();
}
}
LeetCode - 1047. 删除字符串中所有相邻重复项
解题思路:新建一个栈并且遍历字符串中的字母并且同时与栈顶比较,如果和栈顶元素一样则移除,如果不一样就加入栈,最后剩下的就是没有匹配成功的字母,也就是需要求出的结果。这题最后的结果需要的是删除后的字符串,因此这里没有必要真正去建立一个栈,而是可以用字符串来模拟栈的运作方式。
class Solution {
public String removeDuplicates(String s) {
String res = ""; // string as stack
for (int i = 0; i < s.length(); i++) {
if (res.length() > 0 && s.charAt(i) == res.charAt(res.length() - 1)) {
res = res.substring(0, res.length() - 1);
} else {
res += s.charAt(i);
}
}
return res;
}
}