设计带解析函数的表达式树
难度:
标签:
题目描述
代码结果
运行时间: 32 ms, 内存: 0.0 MB
// LeetCode 1628: Design an Expression Tree With Evaluate Function
// Java solution using streams is not typical but here is an approach for demonstration
import java.util.*;
import java.util.function.Function;
import java.util.stream.*;
// Interface for the Node class
interface Node {
public int evaluate();
}
// Abstract class representing a tree node
abstract class TreeNode implements Node {
protected TreeNode left;
protected TreeNode right;
public TreeNode(TreeNode left, TreeNode right) {
this.left = left;
this.right = right;
}
}
// Implementation of operand nodes
class OperandNode extends TreeNode {
private int value;
public OperandNode(int value) {
super(null, null);
this.value = value;
}
@Override
public int evaluate() {
return this.value;
}
}
// Implementation of operator nodes
class OperatorNode extends TreeNode {
private char operator;
public OperatorNode(char operator, TreeNode left, TreeNode right) {
super(left, right);
this.operator = operator;
}
@Override
public int evaluate() {
int leftVal = left.evaluate();
int rightVal = right.evaluate();
switch (operator) {
case '+': return leftVal + rightVal;
case '-': return leftVal - rightVal;
case '*': return leftVal * rightVal;
case '/': return leftVal / rightVal;
default: throw new UnsupportedOperationException("Invalid operator");
}
}
}
// Expression tree class
class TreeBuilder {
public Node buildTree(String[] postfix) {
Deque<TreeNode> stack = new ArrayDeque<>();
Arrays.stream(postfix).forEach(token -> {
if (isOperator(token)) {
TreeNode right = stack.pop();
TreeNode left = stack.pop();
stack.push(new OperatorNode(token.charAt(0), left, right));
} else {
stack.push(new OperandNode(Integer.parseInt(token)));
}
});
return stack.pop();
}
private boolean isOperator(String token) {
return "+-*/".contains(token);
}
}
// Usage example
public class Main {
public static void main(String[] args) {
String[] postfix = {"3", "4", "+", "2", "*", "7", "/"};
TreeBuilder builder = new TreeBuilder();
Node root = builder.buildTree(postfix);
System.out.println(root.evaluate()); // Output should be 2
}
}
解释
方法:
这个题解是基于后缀表达式 (逆波兰表示法) 构建表达式树的方法,并提供了一个节点接口 Node 来计算表达式树的值。首先定义了一个抽象基类 Node,每个节点有左右子节点和节点值。节点值可以是数字或者操作符('+', '-', '*', '/')。如果节点值是数字,则直接返回该值;如果是操作符,则递归地计算左右子节点的值并执行相应的运算。TreeBuilder 类中的 buildTree 方法接受后缀表达式的数组,使用递归的方式从后向前读取数组元素,构建表达式树。如果当前元素是数字,则直接创建节点;如果是操作符,则先递归构建右子树和左子树,因为在后缀表达式中,操作符总是跟在对应的操作数之后。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么构建表达式树时选择从后缀表达式的末尾到开始递归构造,而不是从开始到末尾?
▷🦆
构建表达式树的过程中,如果遇到操作符如何确保已经有足够的操作数节点供操作?
▷🦆
在递归构建表达式树的过程中,如何处理非法的后缀表达式,例如操作符数量不正确或操作数过多的情况?
▷🦆
计算表达式值时,除法操作使用了整数除法`//`。如果输入的后缀表达式预期结果为非整数,这种处理方式是否合适?
▷