今天主要是统一做一下栈与队列,看完了栈实现队列和队列实现栈的视频,发现自己对Stack和Deque类完全没有了解,准备后续补充学习。
232.用栈实现队列
思路:主要是在实现弹出功能的时候栈与队列不统一,想到用一个入栈和一个出栈一起模拟队列弹出的功能。
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() {
dumpStackIn();
return stackOut.pop();
}
public int peek() {
dumpStackIn();
return stackOut.peek();
}
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();
*/
225.用队列实现栈
思路:看了视频讲解后也很明朗了,主要就是把队列的元素先弹出再塞回去,这样做完之后,弹出的顺序就和栈一样了。
class MyStack {
Deque<Integer> que;
public MyStack() {
que = new ArrayDeque<>();
}
public void push(int x) {
que.addLast(x);
}
public int pop() {
int size = que.size();
size--;
while (size-- > 0) {
que.addLast(que.peekFirst());
que.pollFirst();
}
int res = que.pollFirst();
return res;
}
public int top() {
return que.peekLast();
}
public boolean empty() {
return que.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.有效的括号
思路:栈的经典问题,主要思路是想清楚括号不匹配一共有几种情况,要么左括号多要么有括号多,要么括号类型不匹配,一共就这三种情况,想清楚之后就是具体实现,遍历字符串,遇到左括号就把对应的右括号压入栈里,知道遍历到右括号就与栈顶的右括号进行对比,相同就说明匹配成功,可以消去。
想清楚栈的特点之后发现非常适合于这道题目,越往右遍历,碰到的左括号想要匹配上就必须越早出现右括号,而符合栈的先进后出原则。
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();
}
}
1047. 删除字符串中的所有相邻重复项
思路:大致想法自己都有,就是coding的时候不太熟练,还需要再努力练习
class Solution {
public String removeDuplicates(String s) {
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;
}
}
150.逆波兰表达式
思路:大致清楚,但是代码中有很多细节自己没注意,也没扣明白。。比如:
- s.equals('+') 和 '+'.equals(s)效果在这道题里完全不一样。在原始代码中,当
s
为null
时,s.equals('+')
会抛出NullPointerException
异常,导致程序终止。而将比较的顺序改为"+".equals(s)
,在+
字符串调用equals()
方法时,不会引发空指针异常,因为+
字符串不可能为null
。因此,使用"+".equals(s)
可以避免空指针。 -
stack.push(Integer.valueOf(s));这块一开始没明白,差了之后才知道Integer.valueOf(s)可以把字符串转换成整数值并返回一个Integer对象。
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<>();
for (String s : tokens) {
if ("+".equals(s)) {
stack.push(stack.pop() + stack.pop());
}else if ("-".equals(s)) {
stack.push(-stack.pop() + stack.pop());
}else if ("*".equals(s)) {
stack.push(stack.pop() * stack.pop());
}else if ("/".equals(s)) {
int temp1 = stack.pop();
int temp2 = stack.pop();
stack.push(temp2 / temp1);
}else {
stack.push(Integer.valueOf(s));
}
}
return stack.pop();
}
}