#Java #栈和队列
开源学习资料
Feeling and experiences:
对于这个处理字符,括号匹配的问题,在学习数据结构中也遇到过。
数据结构中的做法就是模拟栈,利用栈先进后出的特点。
以下是我第一次写所遇到的问题:
class Solution {
public boolean isValid(String s) {
//先创建一个栈,来进行辅助操作
Stack stack = new Stack<>();
//因为括号只有三种,可以直接都表示出来
//用左括号做参考,把右括号入栈处理
int count =0; //后面又加了count来解决括号数目不一致问题 ,但这样不能解决右括号比左括号多的情况
//如果长度为奇数,则一定不行
if(s.length()%2 == 1){
return false;
}
//遇到右括号,就把右括号入栈
for(int i =0;i
此代码的注释看到很乱,因为我在第一遍写的时候,有很多问题和细节都没有考虑到。
我最开始只判断了左右括号是否匹配的问题,而没有考虑它们数目是否相等。
我的代码思路:以左括号为参考,把对应的右括号入栈,然后去判断这个右括号,如果它与当前的左括号匹配,则出栈。依次这样操作,如果栈为空,说明匹配成功,如果不为空则失败。
大体思路没问题,但里面还有很多细节没有处理。
比如还存在右括号多了的情况(因为是以左括号为参考)。
我就在基础上一步一步增删改查,加了长度判断(因为要匹配,长度为奇数肯定不行),又加了计数器,来判断左右括号数量是否一致(但是判断出现了问题)。
导致思路很混乱,越写越乱。
该代码最后还是没有解决右括号多了的问题。
还是要整理好思路在下手~
其实写完思考一下,以我的方法来写的话,就只要解决了右括号比左括号多的问题就行。
因为我是以左括号为参照,加入栈的只有右括号,而右括号入栈的数量是基于左括号的,在if判断中,遇到了一个左括号就入栈一个右括号。那如果右括号的数量比左括号多,在该代码中是体现不出来的,所以还需要一个条件判断来控制。
因为外层for循环会遍历每一个字符,在if语句中只有遇到左括号才入栈与之对应的右括号,仔细想一下,如果没有遍历到左括号了,也就不会添加右括号,那么在循环里栈为空了,就代表右括号多了。
细品以下代码:
外层for循环会依次遍历执行,遍历到左括号就会入栈一个右括号,此时栈就不是空的了,匹配了再弹出来,这个时候栈空了,但是这一次循环的语句也执行完了,又到下一次循环了。
class Solution {
public boolean isValid(String s) {
Stack stack = new Stack<>();
char ch;
for (int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
//碰到左括号,就把相应的右括号入栈
if (ch == '(') {
stack.push(')');
}else if (ch == '{') {
stack.push('}');
}else if (ch == '[') {
stack.push(']');
} else if (stack.isEmpty() || stack.peek() != ch) {
return false;
}else {//如果是右括号判断是否和栈顶元素匹配
stack.pop();
}
}
//最后判断栈中元素是否匹配
return stack.isEmpty();
}
}
因为是栈和队列的练习,就先不写map集合的解答了。
删除相邻且相同的元素很简单,但是如上述示例:删除了还要合并后再判断。(类似消消乐)
一次一次操作,那这样效率就太低了。
class Solution {
public String removeDuplicates(String s) {
//利用栈,先依次把字符串中的元素入栈,遇到遍历的元素与栈顶元素相同,则出栈栈顶元素
Deque deque = new LinkedList<>();
StringBuffer res = new StringBuffer();
for(int i=0;i
本次我是用到了双端队列,这样就既可以用模拟栈来消除元素后,再模拟队列存放结果。
实现了栈和队列的结合使用。
注意判断栈空的情况,不然会容易抛出异常。
特别是在:if(deque.isEmpty() || ch != deque.peek()),为什么会去判断是否为空?
1. 如果栈为空,直接将当前字符入栈,因为栈中没有元素,无需比较。
2. 如果栈不为空,检查当前字符是否与栈顶元素不同,如果不同,则入栈;如果相同,则说明有相邻重复字符,出栈栈顶元素。
通过这个条件,代码能够正确处理栈为空的情况,避免了潜在的空栈异常。
该题目,最开始还没有读懂是什么意思。
后面看了代码随想录的文字讲解,又把该问题转变为了栈的运用。
在力扣的官方解答中,也有动态示意图
把题意理解到了就非常好做了
class Solution {
public int evalRPN(String[] tokens) {
Deque deque = new LinkedList<>();
for(int i =0;i
练习完以上的题目,有很多的收获。
题目的难度是依次递增的,但花费的时间也是递增的。虽然第一个题是最简单的,但是存在的细节也很多。昨天归纳完了栈和队列的模拟与总结了方法,今天就是实战。
从做题的流程下来,在第一个题上反而花费了最多的时间,很多条件的判断是最开始是没想到的,到慢慢琢磨,细品。把第一个题的问题处理完后,再来做后面的题就越来越快了。
今日的三道题主要是用到了栈的原理,还要多加巩固API的使用和对栈结构的处理!
回廊一寸相思地
落月成孤倚~
Fighting!