题目地址:
https://www.lintcode.com/problem/convert-expression-to-reverse-polish-notation/description
给定一个中缀表达式,要求将其转化为后缀表达式。
经典的做法是用栈。以一个栈st
保存操作符(这里操作符包括括号。但实际算法中只存左括号不存右括号),再以一个list(变量名为res
)存最后的后缀表达式。具体算法如下:
1、如果遇到操作数或者左括号,则直接进res
;
2、如果遇到右括号,则将栈中(
到栈顶的所有操作符都弹出来append到res
后面;
3、如果遇到操作符,则比较该操作符与栈顶的优先级,如果栈顶优先级高或等于该操作符,则将栈顶弹出并append到res
后面,直到栈顶优先级低于该操作符为止,再将该操作符进栈。由于左括号在遇到右括号之前是不会弹出的,所以很自然地规定左括号优先级最小。
如此这般直到中缀表达式被遍历完毕。代码如下:
import java.util.*;
public class Solution {
/**
* @param expression: A string array
* @return: The Reverse Polish notation of this expression
*/
public List<String> convertToRPN(String[] expression) {
// write your code here
List<String> res = new ArrayList<>();
// 开一个哈希表记录每个操作符的优先级。数字大者优先级高
Map<String, Integer> prec = new HashMap<>();
prec.put("(", 1);
prec.put("+", 2);
prec.put("-", 2);
prec.put("*", 3);
prec.put("/", 3);
Deque<String> stack = new ArrayDeque<>();
for (String s : expression) {
if (!prec.containsKey(s) && !")".equals(s)) {
// 如果是操作数则直接append到res后面
res.add(s);
} else if ("(".equals(s)) {
// 如果是左括号则直接进栈
stack.push(s);
} else if (")".equals(s)) {
// 如果是右括号,则将左括号以上的所有操作符append到res后面,并把左括号自己也出栈
while (!"(".equals(stack.peek())) {
res.add(stack.pop());
}
stack.pop();
} else {
// 如果遇到操作符,则将栈顶开始所有优先级更高的或相等的操作符都出栈append到res后面;
// 接着再把新来的操作符入栈
while (!stack.isEmpty() && prec.get(stack.peek()) >= prec.get(s)) {
res.add(stack.pop());
}
stack.push(s);
}
}
// 最后把从栈顶到栈底的所有操作符append到res后面
res.addAll(stack.pop());
return res;
}
}
时空复杂度。