目录
栈与队列
这里说的栈与队列可以理解为容器适配器,各自有其接口,比如栈有push、pop,符合先进后出的规则,其底层结构主要为数组和链表。而队列符合先进先出的规则,其底层结构默认是以deque
232. 用栈实现队列
public 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() {
// 只有当out为空时才从in导数据
if (stackOut.isEmpty()) {
while (!stackIn.isEmpty()) {
stackOut.push(stackIn.pop());
}
}
return stackOut.pop();
}
public int peek() {
int popData = this.pop();
stackOut.push(popData);
return popData;
}
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
}
225. 用队列实现栈
一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。
public class MyStack {
Queue<Integer> queue;
public MyStack() {
queue = new LinkedList<>();
}
public void push(int x) {
queue.add(x);
}
public int pop() {
rePosition();
return queue.poll();
}
public int top() {
rePosition();
int result = queue.poll();
queue.add(result);
return result;
}
public boolean empty() {
return queue.isEmpty();
}
private void rePosition() {
int size = queue.size();
size--;
while (size-- > 0) {
queue.add(queue.poll());
}
}
}
20. 有效的括号
括号匹配是使用栈解决的经典问题
分析不匹配情况:
因为题目要求:左右匹配、顺序匹配、类型要匹配,因而我们可以在遍历时将对应的右边括号放到栈内,遍历左边结束后,就可从栈中取出来进行比对。
public class ValidParentheses {
public boolean isValid(String s) {
// 因为要求成对匹配,所以长度为奇数时,返回错误
if (s.length() % 2 != 0) {
return false;
}
LinkedList<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();
}
}
1047. 删除字符串中的所有相邻重复项
属于匹配问题,依然用栈来解决
public class RemoveAdjacentDuplicates {
/**
* 使用 Deque 作为堆栈
* @param s
* @return
*/
public String removeDuplicatesByStack(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() || ch != deque.peek()) {
deque.push(ch);
}else {
deque.pop();
}
}
// 剩余的元素拼接即可
String str = "";
while (!deque.isEmpty()) {
str = deque.pop() + str;
}
return str;
}
/**
* 字符串直接作为栈,省去了栈还要转为字符串的操作。
* @param s
* @return
*/
public String removeDuplicatesByString(String s) {
// 可以用StringBuffer代替栈,用StringBuilder更快
// StringBuilder res = new StringBuilder();
StringBuffer res = new StringBuffer();
// 栈顶指针
int top = -1;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (top >= 0 && res.charAt(top) == ch) {
res.deleteCharAt(top);
top--;
}else {
res.append(ch);
top++;
}
}
return res.toString();
}
}