Algorithm 检查两个数学表达式是否相等

Algorithm 检查两个数学表达式是否相等,algorithm,tree,Algorithm,Tree,我在面试中遇到了一个问题。我试图解决这个问题,但没有找到解决办法。问题是: [已编辑] 第一部分:给出两个表达式,其中只有“+”运算符,请检查给定的两个表达式是否在数学上等价。 例如,“A+B+C”相当于“A+(B+C)” 第二部分:给您两个表达式,其中只有“+”和“-”运算符,请检查给定的两个表达式是否在数学上等价。 例如,“A+B-C”相当于“A-(-B+C)” 我的思考过程:我在思考如何从给定的表达式中构建表达式树,并寻找某种相似性。但我无法想出一个好方法来检查两个表达式树是否在某种程度上

我在面试中遇到了一个问题。我试图解决这个问题,但没有找到解决办法。问题是:

[已编辑] 第一部分:给出两个表达式,其中只有“+”运算符,请检查给定的两个表达式是否在数学上等价。 例如,“A+B+C”相当于“A+(B+C)”

第二部分:给您两个表达式,其中只有“+”和“-”运算符,请检查给定的两个表达式是否在数学上等价。 例如,“A+B-C”相当于“A-(-B+C)”

我的思考过程:我在思考如何从给定的表达式中构建表达式树,并寻找某种相似性。但我无法想出一个好方法来检查两个表达式树是否在某种程度上相同


有人能帮我吗:)提前谢谢

只要操作是可交换的,我建议的解决方案是分配括号操作,然后按“变量”对术语进行排序,然后在它们之间运行聚合器,您应该得到一系列因子和符号。然后只需检查一组因素

聚合变量计数,直到遇到一个大括号,将减法视为求反变量的加法。递归地处理子表达式

子表达式的内容可以直接聚合到计数中,您只需要正确地考虑符号——不需要为此任务创建实际的表达式树。代码中使用的
TreeMap
只是JDK中的一个排序映射实现

代码利用了当前位置是
读取器
状态的一部分这一事实,因此我们可以轻松地在递归调用的结束括号之后继续解析,而无需以某种方式将此信息显式地返回给调用方

Java实现(未经测试):

p.S:添加了一个
toString()
方法来更好地说明数据结构

例如,应打印
1A+1B+-1C


p.p.p.p.S.:修复、简化、更好的解释。

您可以从左到右解析表达式,并将其简化为标准形式,以便以直观的方式进行比较;唯一复杂的是,当你遇到一个结束括号时,你需要知道它的相关开始括号前面是否有加号或减号;你可以使用一个堆栈来实现这一点;e、 g:

函数字典(){
这个.d=[];
}
Dictionary.prototype.add=函数(键、值){
如果(!this.d.hasOwnProperty(key))this.d[key]=值;
否则该.d[key]+=值;
}
Dictionary.prototype.compare=函数(其他){
for(此.d中的var键){
如果(!other.d.hasOwnProperty(key)| | other.d[key]!=this.d[key])返回false;
}
返回this.d.length==other.d.length;
}
函数规范化(表达式){
变量标记=表达式.split(“”);
var variables=newdictionary();
var符号_堆栈=[];
var总符号=1;
无功电流符号=1;
for(令牌中的var i){
交换机(令牌[i]){
格“(”:{
符号栈。推(当前符号);
总符号*=当前符号;
当前符号=1;
打破
}
案例“)”:{
total_sign*=sign_stack.pop();
打破
}
格“+”:{
当前符号=1;
打破
}
案例'-':{
当前_符号=-1;
打破
}
案例“”:{
打破
}
默认值:{
添加(标记[i],当前符号*总符号);
}
}
}
返回变量;
}
VarA=规范化(“a+B+(a-(a+C-B)-B)-C”);
var b=规范化(“-C-(-A-(b+(-C))”);

写作(a.比较(b))A-B=!=B-A,所以它们在这里不是可交换的,实际上:加法是可交换的。因子的符号不同:[1]A+[-1]B=!=[1] B+[-1]艾米:重点是减法不是可交换的,所以我不确定你的答案如何应用于这个问题减法是否定的加法。重点是你不计算变量,只计算常数因子,直到你达到每个变量只有一个项的状态。你想为这样的表达式发明一个新的方法吗。
class Expression {
   // Count for each variable name
   Map<String, Integer> counts = new TreeMap<>();

   Expression(Srring s) throws IOException {
     this(new StringReader(s));
   }

   Expression(Reader reader) throws IOException {
     int sign = 1;
     while (true) {
       int token = reader.read(); 
       switch (token) {
         case -1:  // Eof
         case ')':
           return;
         case '(':
           add(sign, new Expression(reader));
           sign = 1;
           break;
         case '+':
           break;
         case '-':
           sign = -sign;
           break;
         default:
           add(sign, String.valueOf((char) token));
           sign = 1;
           break;
       }
     }
   }

   void add(int factor, String variable) {
     int count = counts.containsKey(variable) ? counts.get(variable) : 0;
     counts.put(count + factor, variable);
   }

   void add(int sign, Expression expr) {
     for (Map.Entry<String,Integer> entry : expr.counts.entrySet()) {
       add(sign * entry.getVaue(), entry.getKey());
     }
   }

   void equals(Object o) {
     return (o instanceof Expression) 
        && ((Expression) o).counts.equals(counts);
   }

   // Not needed for the task, just added for illustration purposes.
   String toString() {
     StringBuilder sb = new StringBuilder();
     for (Map.Entry<String,Integer> entry : expr.counts.entrySet()) {
       if (sb.length() > 0) {
         sb.append(" + ");
       }
       sb.append(entry.getValue());  // count
       sb.append(entry.getKey());    // variable name
     }
     return sb.toString();
   }
 }
new Expression("A+B-C").equals(new Expression("A-(-B+C)"))