这个递归 - 回溯解决方案如何解决算术表达问题?

时间:2017-11-19 08:00:06

标签: java recursion arithmetic-expressions recursive-backtracking

我正在尝试解决这个算术表达式问题 我在数组中取n个(这里是5个)元素并尝试(+ - *)中所有运算符的组合来查找表达式是否可被101整除 在这里,我们不关心运营商的顺序......不使用BODMAS 输入

5

55 3 45 33 25

输出

55 + 3-45 * 33-25

我是递归和回溯的新手。我试图了解问题的哪一部分是错误的

这是我的代码:

  public static boolean solve(char []operators,long[]nums,long res,int index,Stack<Character>st){


    if(index+1==nums.length){ //reached end of number array
        if(res%101==0){
            System.out.println(res);
            return true;
        }
        return false;
    }

    for(int i=0;i<operators.length;i++){
        char op=operators[i]; //try the operator
        long num1=nums[index];
        long num2=nums[index+1]; //LINE1

        System.out.println("trying "+num1+""+op+" num2="+num2);
        res=performOp(op,num1,num2);
        nums[index+1]=res; 

        st.push(op);
        if(solve(operators,nums,res,index+1,st)){
            return true;
        }
        //backtrack
        //return to earlier state than try another operator

        //LINE2
        nums[index+1]=performBackTrack(op,num1,num2); //restoring number
        System.out.println("num2="+num2+" num1="+num1+" after backtrack");
        st.pop();

    }

    return false;
} 

  public static long performBackTrack(char op,long num1,long num2){
    //trying to restore numbers
    switch(op){
        case '+':return num2-num1;
        case '-':return num1-num2;
        case '*':return num1/num2;
        default:return 0L;
    }
}

 public static long performOp(char op,long num1,long num2){
    switch(op){
        case '+':return num1+num2;
        case '-':return num1-num2;
        case '*':return num1*num2;
        default:return 0L;
    }
}

在回溯之后,当我在LINE2进行更改并进入循环以尝试下一个操作符时,更改工作正常,因为我在LINE2返回了原始数字,但它没有反映在LINE1,我尝试的最后一个数字尝试运算符之前的恢复不会反映在LINE1。

请帮助......我们将不胜感激任何帮助...

1 个答案:

答案 0 :(得分:0)

您的反向跟踪方法存在错误。

您执行res=performOp(op,num1,num2)并分配nums[index+1]的结果。

让我们考虑所有可能的操作以及如何逆转它们:

res = num1 + num2      ->  num2 = res - num1
res = num1 - num2      ->  num2 = num1 - res
res = num1 * num2      ->  num2 = res / num1

因此,您应该将resnum1传递给performBackTrack,而不是num1num2

除此之外,performBackTrack应如下所示:

public static long performBackTrack(char op,long res,long num1) {
//trying to restore numbers
    switch(op){
        case '+':return res - num1;
        case '-':return num1 - res;
        case '*':return res / num1;
        default:return 0L;
    }
}

并且对performBackTrack的调用应为:

nums[index+1]=performBackTrack(op,res,num1);

这会产生(对于您的给定输入)以下输出:

trying 55+ num2=3
trying 58+ num2=45
trying 103+ num2=33
trying 136+ num2=25
num2=25 num1=136 after backtrack
trying 136- num2=25
num2=25 num1=136 after backtrack
trying 136* num2=25
num2=25 num1=136 after backtrack
num2=33 num1=103 after backtrack
trying 103- num2=33
trying 70+ num2=25
num2=25 num1=70 after backtrack
trying 70- num2=25
num2=25 num1=70 after backtrack
trying 70* num2=25
num2=25 num1=70 after backtrack
num2=33 num1=103 after backtrack
trying 103* num2=33
trying 3399+ num2=25
num2=25 num1=3399 after backtrack
trying 3399- num2=25
num2=25 num1=3399 after backtrack
trying 3399* num2=25
num2=25 num1=3399 after backtrack
num2=33 num1=103 after backtrack
num2=45 num1=58 after backtrack
trying 58- num2=45
trying 13+ num2=33
trying 46+ num2=25
num2=25 num1=46 after backtrack
trying 46- num2=25
num2=25 num1=46 after backtrack
trying 46* num2=25
num2=25 num1=46 after backtrack
num2=33 num1=13 after backtrack
trying 13- num2=33
trying -20+ num2=25
num2=25 num1=-20 after backtrack
trying -20- num2=25
num2=25 num1=-20 after backtrack
trying -20* num2=25
num2=25 num1=-20 after backtrack
num2=33 num1=13 after backtrack
trying 13* num2=33
trying 429+ num2=25
num2=25 num1=429 after backtrack
trying 429- num2=25
404

并返回true

编辑:

实际上,这要简单得多。您不需要performBackTrack。 只需替换

nums[index+1]=performBackTrack(op,num1,num2); //restoring number

nums[index+1]=num2;

毕竟,您尝试将nums[index+1]分配给作业nums[index+1]=res;之前的值num2,这正是file.setLastModified(creationDate);