LeetCode棧的基礎操作系列問題詳細總結
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//b////c/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!");
}
}
}