题目地址:
https://leetcode.com/problems/build-binary-expression-tree-from-infix-expression/
给定一个中缀表达式 s s s,里面含数字、左右括号和加减乘除,题目保证每个数字只有一个字符的长度。要求将其转为表达式树。
思路参考https://blog.csdn.net/qq_46105170/article/details/106212914。下面简要说明之:
首先规定各个运算符的优先级,这里左括号也视为运算符,其优先级为
1
1
1,加减优先级为
2
2
2,乘除为
3
3
3。维护一个符号栈,使得从栈底到栈顶运算符优先级严格上升,再开一个Node栈,来存Node。接着开始遍历
s
s
s:
1、遇到左括号,则入符号栈;
2、遇到数字,则new出节点入Node栈;
3、遇到右括号,则只要符号栈栈顶不是左括号,就从Node栈里pop两个Node出来分别作为右左孩子(注意,这里是右左孩子不是左右孩子,先pop的是右孩子,后pop的是左孩子),从符号栈里pop出一个运算符作为树根,连上左右孩子之后再push回Node栈;最后将左括号出栈;
4、遇到运算符,则只要符号栈栈顶的运算符优先级大于等于新来的运算符,就从Node栈里pop两个Node出来分别作为右左孩子,从符号栈里pop出一个运算符作为树根,连上左右孩子之后再push回Node栈。
最后,如果发现Node栈size不为 1 1 1,就再进行上面的pop两次连树根的操作,直到Node栈size为 1 1 1。最后这个留在栈里的Node即为所求。代码如下:
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
public class Solution {
public Node expTree(String s) {
Map<Character, Integer> prio = new HashMap<>();
prio.put('(', 1);
prio.put('+', 2);
prio.put('-', 2);
prio.put('*', 3);
prio.put('/', 3);
Deque<Character> ops = new ArrayDeque<>();
Deque<Node> stack = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch == '(') {
ops.push(ch);
} else if (Character.isDigit(ch)) {
stack.push(new Node(ch));
} else if (ch == ')') {
while (ops.peek() != '(') {
combine(ops, stack);
}
// pop掉左括号
ops.pop();
} else {
while (!ops.isEmpty() && prio.get(ops.peek()) > prio.get(ch)) {
combine(ops, stack);
}
ops.push(ch);
}
}
while (stack.size() > 1) {
combine(ops, stack);
}
return stack.peek();
}
private void combine(Deque<Character> ops, Deque<Node> stack) {
Node root = new Node(ops.pop());
// 先pop的是右孩子,然后是左孩子
root.right = stack.pop();
root.left = stack.pop();
stack.push(root);
}
}
class Node {
char val;
Node left, right;
public Node(char val) {
this.val = val;
}
}
时空复杂度 O ( n ) O(n) O(n)。