1、括号匹配问题
. - 力扣(LeetCode)
1.1 思路分析
根据栈的先进后出原则,我们可以这样解决问题:
遍历字符串,遇见左括号就将左括号push入栈;遇见右括号就pop出栈,将出栈的元素和该右括号比较是否匹配,若匹配则继续遍历并比较,若不匹配则直接返回false。细分为以下几种情况:
1.匹配(左右括号数量相同且匹配):字符串遍历完,且栈为空(右括号与左括号数量相等,且均匹配),则说明括号匹配,返回true。
2.不匹配(括号不匹配):遍历到的右括号和出栈的左括号比较是否匹配,一旦不匹配,立即返回false。
3.不匹配(左括号数量多):当字符串遍历完后,发现栈还不为空,则说明左括号多,不匹配。
4.不匹配(右括号多):遍历遇见右括号需将栈顶的左括号出栈,若要出栈时栈为空,则说明右括号多,不匹配。
1.2 代码
public boolean isValid(String s) {//利用栈先进后出特点 解决问题Stack<Character> stack = new Stack<>();//遍历字符串for(int i = 0; i < s.length(); i++) {char ch = s.charAt(i);//若为左括号 将括号入栈if(ch == '(' || ch == '{' || ch == '[') {stack.push(ch);}else {//遍历到的为右括号 进入else//若栈为空 则说明右括号多 立即返回falseif(stack.isEmpty()) {return false;}//若栈不为空 则pop出栈 比较是否匹配 char ch2 = stack.pop();switch(ch) {//使用switch语句比较是否匹配 一旦不匹配 立即返回falsecase ')':if(ch2 != '(') {return false;}break;case ']':if(ch2 != '[') {return false;}break;case '}':if(ch2 != '{') {return false;}break;}}}//遍历完成且栈为空 则说明匹配 if(!stack.isEmpty()) {return false;}return true;}
2、栈的弹出、压入序列
2.1 思路分析
以i遍历pushV,每次都将将i下标的元素入栈,再将栈顶元素和j下标元素比较,
若相等:则出栈,j++,i++
不相等:则i++,j保持原位
注意:j++后,j下标与栈顶元素可能依然相等,此时要连续出栈。即j变化后,要继续和栈顶元素比较。
- i遍历完成,且j也遍历也完成(此时栈肯定为空),说明出栈序列匹配
- 若i遍历完成后,j还没有遍历完成(栈不为空),则说明出栈序列不匹配
因为只有栈顶元素和j下标元素相等时,才会出栈,j++
2.2 代码
public boolean IsPopOrder (int[] pushV, int[] popV) {Stack<Integer> stack = new Stack<>();int j = 0;for (int i = 0; i < pushV.length; i++) {//每次循环都会将pushV中i下标的元素入栈stack.push(pushV[i]);//因为j++后,元素可能连续出栈,所以要while循环//出栈后,栈可能出现空的情况,!stack.isEmpty(),防止出现空指针异常while (!stack.isEmpty() && stack.peek() == popV[j]) {j++;//若j下标和栈顶元素相同,则出栈stack.pop();}}//i遍历完成,若此时j也遍历完成(j == popV.length),则说明出栈序列匹配return j == popV.length;}
3、逆波兰表达式(后缀表达式)求值
. - 力扣(LeetCode)
3.1 什么是逆波兰表达式
逆波兰表达式,也称为后缀表达式,是一种表达式的表示方法,其中运算符位于操作数之后。
后缀表达式由中缀表达式转化而来,可以实现表达式的求值和计算,提高了计算机内存访问的效率。而中缀表达式就是我们平时做运算的表达式。
那么如何将中缀表达式转换为后缀表达式?
- 从左向右,以先乘除后加减的次序加括号
- 将括号中的相邻两项的运算符拿到括号的后面
- 去掉所有括号
3.2 后缀表达式如何求值(思路分析)
我们拿到后缀表达式后,
- 遍历表达式,若是非操作符元素(数字元素),则入栈
- 若遇到操作符元素,则出栈两次,将第一次出栈的元素val2作为该操作符的右操作数,将第二次出栈的元素val1作为该操作符的左操作数,接着将所得结果入栈。
- 继续遍历,并重复以上操作
- 遍历完成后,栈中只剩一个元素,该元素就是后缀表达式的值。
3.3 代码
class Solution {public int evalRPN(String[] tokens) {Stack<Integer> stack = new Stack<>();for (int i = 0; i < tokens.length; i++) {String str = tokens[i];if (!isOperator(str)) {//如果不是是操作符//则元素入栈int val = Integer.parseInt(str);//将字符串转化为整型stack.push(val);} else {//如果是操作符//则弹出栈顶两个元素//计算结果,并将结果入栈int val2 = stack.pop();int val1 = stack.pop();if (str.equals("+")) {stack.push(val1 + val2);}if (str.equals("-")) {stack.push(val1 - val2);}if (str.equals("*")) {stack.push(val1 * val2);}if (str.equals("/")) {stack.push(val1 / val2);}}}//遍历完成后,栈中还有一个元素//该元素就是后缀表达式的值return stack.pop();}//判断该元素是否为操作符private boolean isOperator(String str) {if (str.equals("+") || str.equals("-")|| str.equals("*") || str.equals("/")) {return true;}return false;}
}