LeetCode中考察栈的基础操作的问题有20. Valid Parentheses,71. Simplify Path,150. Evaluate Reverse Polish Notation等,本文对这三个题进行详细的解析。
栈是一种特殊的线性表,仅能在线性表的一端操作,栈顶允许操作,栈底不允许操作是一种先进后出(LIFO)的数据结构。其最基础的操作包括创建一个栈(Stack())、入栈(push(E item))和出栈(pop())。下面是相关的Java API。
接下来使用这些基础操作来解决实际问题:
LeetCode 20. Valid Parentheses
Description:
Given a string containing just the characters ‘(’, ‘)’, ‘{’, ‘}’, ‘[’ and ‘]’, determine if the input string is valid.
An input string is valid if:
- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
Note that an empty string is also considered valid.
Example 1:
Input: "()"
Output: true
Example 2:
Input: "()[]{}"
Output: true
Example 3:
Input: "(]"
Output: false
Example 4:
Input: "([)]"
Output: false
Example 5:
Input: "{[]}"
Output: true
思路解析:
题意是给定一个包含括号的字符串,判断是否可以匹配。
本题考查栈的基础应用,可以利用栈的入栈、出栈操作完成解答。
对字符串的每个字符进行遍历,如果是左括号,进行入栈操作;
这一步完成需要判断一下栈是否为空,也就是说如果刚开始的是右括号的话,明显是不可匹配的,直接返回false;
上面已经判断了不是左括号,接着就要判断右括号和栈顶的括号(执行pop()操作)是否匹配,不匹配直接返回false;
最后注意遍历完成以后,如果全部匹配的话,push()和pop()操作是成对出现的,返回的是stack.isEmpty(),这样也可以保证了题目中“Note that an empty string is also considered valid”,空串也认为是可以匹配的。
代码如下:
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0 ; i < s.length() ; i ++){
char c = s.charAt(i);
if(c == '(' || c == '[' || c == '{'){
stack.push(c);
} else{
if(stack.isEmpty()){
return false;
}
char topChar = stack.pop();
if(c == ')' && topChar != '(')
return false;
if(c == ']' && topChar != '[')
return false;
if(c == '}' && topChar != '{')
return false;
}
}
return stack.isEmpty();
}
}
LeetCode 71. Simplify Path
Description:
Given an absolute path for a file (Unix-style), simplify it.
For example,
path = “/home/”, => “/home”
path = “/a/./b/…/…/c/”, => “/c”
path = “/a/…/…/b/…/c//.//”, => “/c”
path = “/a//bc/d//././/…”, => “/a/b/c”
In a UNIX-style file system, a period (’.’) refers to the current directory, so it can be ignored in a simplified path. Additionally, a double period ("…") moves up a directory, so it cancels out whatever the last directory was. For more information, look here: https://en.wikipedia.org/wiki/Path_(computing)#Unix_style
Corner Cases:
- Did you consider the case where path = “/…/”?
In this case, you should return “/”. - Another corner case is the path might contain multiple slashes ‘/’
together, such as “/home//foo/”. In this case, you should ignore
redundant slashes and return “/home/foo”.
思路解析:
本题题意是简化路径,考查栈的基础操作。
具体操作是把路径看做是由一个或多个"/“分割开的多个子字符串,把它们分别提取出来进行处理。如果是”.“的情况直接去掉,是”…“时删掉它上面挨着的一个路径;如果是空的话返回”/",如果有多个"/"只保留一个。
对应于栈,如果是"…",出栈;如果不是".“或者”…",也不为空,入栈。
代码如下:
class Solution {
public String simplifyPath(String path) {
Stack<String> stack = new Stack<>();
String[] p = path.split("/");
for (String t : p) {
if (!stack.isEmpty() && t.equals("..")) {
stack.pop();
} else if (!t.equals(".") && !t.equals("") && !t.equals("..")) {
stack.push(t);
}
}
List<String> list = new ArrayList(stack);
return "/" + String.join("/", list);
}
}
LeetCode 150. Evaluate Reverse Polish Notation
Description:
Evaluate the value of an arithmetic expression in Reverse Polish Notation.
Valid operators are +, -, *, /. Each operand may be an integer or another expression.
Note:
- Division between two integers should truncate toward zero.
- The given RPN expression is always valid. That means the expression
would always evaluate to a result and there won’t be any divide by
zero operation.
Example 1:
Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9
Example 2:
Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6
Example 3:
Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
Output: 22
Explanation:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
思路解析:
本题是要计算逆波兰表达式的值,主要考查栈的基础应用,入栈和出栈操作。
具体做法:从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,进行运算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,得出的值即为表达式的结果。
更多关于逆波兰表达式可以参考https://blog.csdn.net/u014116780/article/details/82964481
代码如下:
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<Integer>();
for(int i=0;i<tokens.length;i++){
if(isInteger(tokens[i])){
stack.push(Integer.parseInt(tokens[i]));
}else{
int num1 = stack.pop();
int num2 = stack.pop();
int res = operate(tokens[i],num1,num2);
stack.push(res);
}
}
return stack.pop();
}
public boolean isInteger(String string){
try{
if(Integer.parseInt(string)>=Integer.MIN_VALUE && Integer.parseInt(string)<=Integer.MAX_VALUE){
return true;
}
}catch(Exception e){
return false;
}
return false;
}
public int operate(String operation, int num1, int num2){
if("+".equals(operation)){
return num1 + num2;
}else if("*".equals(operation)){
return num1 * num2;
}else if("/".equals(operation)){
return num2 / num1;
}else if("-".equals(operation)){
return num2 - num1;
}else{
throw new RuntimeException("operation error!");
}
}
}