题目描述 & 链接
Leetcode 1597: 根据计算表达式生成二叉树,使得二叉树的中序遍历结果与计算表达式相同
题目思路
对于计算表达式的题目,通常能使用双栈思路求解,这道题思路与Leetcode 772. Basic Calculator III (计算器 III) 基本相同,唯一不同只是处理结果上,之前直接计算出结果即可,这里需要建成二叉树节点,所以数字栈保存的是当前树节点,计算过程是将栈顶pop出来,作为树根,将数字栈pop出两个节点作为左右叶子节点,与树根相连,然后将该树根重新加入数字栈
基本思路
- 初始化两个栈,一个符号栈,一个数字栈
- 遍历表达式每一个字符串
- 如果当前是左括号,直接进栈
- 如果是右括号进栈,那么触发计算,直到栈顶是左括号为止
- 如果是数字,那么将数字作为叶子节点加入数字栈
- 如果是运算符号,那么维护符号栈的单调递增性,如果新加入符号优先级小于等于栈顶优先级,那么触发计算,直到栈为空或者栈顶优先级更小
- 最后返回结果
代码如下:
/**
* Definition for a binary tree node.
* class Node {
* char val;
* Node left;
* Node right;
* Node() {this.val = ' ';}
* Node(char val) { this.val = val; }
* Node(char val, Node left, Node right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public Node expTree(String s) {
// 除了()括号外的符号位都是作为parent节点存在
// 数字位作为叶子节点存在
// 符号分隔优先级,按照优先级将
// 维护两个栈,一个单调递减栈 (符号优先级排序)
HashMap<Character, Integer> prio = new HashMap<>();
prio.put('+', 2);
prio.put('-', 2);
prio.put('*', 3);
prio.put('/', 3);
prio.put('(', 1);
Deque<Character> ops = new ArrayDeque<>();
Deque<Node> stk = new ArrayDeque<>();
for(int i=0; i<s.length(); i++) {
if(s.charAt(i)=='(') {
ops.push(s.charAt(i));
} else if(s.charAt(i)==')') {
while(ops.peek()!='(') {
combine(ops, stk);
}
ops.pop(); // pop (
} else if(Character.isDigit(s.charAt(i))) {
stk.push(new Node(s.charAt(i)));
} else {
// 维护单调栈 - 如果新加入元素优先级小于等于栈顶优先级,触发计算
while(!ops.isEmpty() && prio.get(s.charAt(i))<=prio.get(ops.peek())) {
combine(ops, stk);
}
ops.push(s.charAt(i));
}
}
// if all ops are same prio
while(stk.size()>1) {
combine(ops, stk);
}
return stk.peek();
}
private void combine(Deque<Character> ops, Deque<Node> stk) {
Node root = new Node(ops.pop());
root.right = stk.pop();
root.left = stk.pop();
stk.push(root);
}
}
时间复杂度:;空间复杂度:, 树深度,总节点数 。