在Java中实现递归

在Java中实现递归,java,recursion,Java,Recursion,我想说清楚,这不是家庭作业,我在自己的时间学习计算机科学 我最近买了一本查尔斯·菲利普斯的书,书名为《逻辑思维的50个谜题》。我启动了其中一个,我想到我可以用递归解决这个问题。以下是(意译)问题: 在每个空间中插入一个数学运算符(+、-、÷、x),以解方程: 6 3 5 7 4 8=13 我的理解是,为了使用递归解决这个问题,我首先需要确定一个基本情况。然而,我做这件事有困难 所以我的问题是,什么是可能的基本情况,我应该如何开始实施它?递归函数会是什么样子(参数、返回类型等)?(请使用代码) 这

我想说清楚,这不是家庭作业,我在自己的时间学习计算机科学

我最近买了一本查尔斯·菲利普斯的书,书名为《逻辑思维的50个谜题》。我启动了其中一个,我想到我可以用递归解决这个问题。以下是(意译)问题:

在每个空间中插入一个数学运算符(+、-、÷、x),以解方程:

6 3 5 7 4 8=13

我的理解是,为了使用递归解决这个问题,我首先需要确定一个基本情况。然而,我做这件事有困难

所以我的问题是,什么是可能的基本情况,我应该如何开始实施它?递归函数会是什么样子(参数、返回类型等)?(请使用代码)

这就是我到目前为止所做的:我认为几乎可以工作了

请参阅我的答案以了解实现方法


注意:我使用的是Java,基本情况是所有空格都用运算符填充。您可以使用深度优先回溯搜索解决此问题:

algorithm dfs(i):
    if i == num_blanks:  # base case: filled in all the blanks
        if equation_solved():
            return the operators you filled in
    else:
        for op in (+, -, ÷, ×):
            blank[i] = op
            if dfs(i + 1) returns a solution:
                return that solution
            blank[i] = _     # restore to previous state

这是一种在整个组合空间中进行递归搜索的方法。(我希望这不会破坏您的练习;我用伪代码编写了它,将实现留给您。)

我认为停止条件应该意味着等式得到满足:所有运算符都已填充,并且操作会产生适当的等式

我将把这个方程表示为一个解析树,叶子作为数字,父元素作为操作符。树自然适合递归,因为它是一个层次数据结构


假设操作符的根操作是负号,右子操作是期望值(13),左子操作是左手边。添加一个操作符,评估树,然后回溯,直到满足停止条件。

您可以将其视为决策树

              6
        /    /    \    \
        +   -     *    /
        3                    Assuming you choose + for the first operator
/    /       \    \
+   -        *    /
5   5        5    5
    ^             ^
    6 + 3 - 5     6 + 3 / 5

然后可以使用图遍历算法(如DFS或BFS)来检查结果。两者都是自然递归的。

下面是我最后的实现,但首先是对问题解决方案的解释:

  • 基本情况(如larsmans和Jan Dvorak所说)是当所有的“10;”都由运算符(如“+”)填充时
  • 该函数调用自身,每次添加另一个参数,直到达到不正确的基本情况(例如“6+3+5+7+4-8=13”)或有正确答案为止
  • 如果基本情况是不正确的,那么我们会不断弹出级别,我们可以通过一个操作符更改级别
代码如下:

class GapFill {

    private static String numbers; //E.g. 6_5_4=15
    private static String[] blank; //Array of operators to go in the blanks

    //Where:
    //p = plus
    //m = minus
    //d = divide
    //t = times
    private static String[] operators = {"p", "m", "d,", "t"};

    public static void main(String[] args) {
        numbers = args[0];
        blank = new String[numbers.split("_").length - 1];
        if(dfs(0)) { //If a solution was found
            int count = 0;
            while(numbers.indexOf("_")!=-1) {
                int index = numbers.indexOf("_");
                numbers = numbers.substring(0,index)+blank[count]+numbers.substring(index+1);
                count++;
            }
            System.out.println(numbers);
        }
    }

    private static boolean dfs(int i) {
        if(i == blank.length) {  //base case: filled in all the blanks
            return solveEquation();
        }
        for(String op : operators) {
            blank[i] = op;
            if(dfs(i + 1)) {
                return true;
            }
        }
        blank[i] = "_"; //restore to previous state
        return false;
    }

    private static boolean solveEquation() {
        String[] eachNumber = numbers.substring(0, numbers.indexOf("=")).split("_");
        String finalResult = numbers.substring(numbers.indexOf("=")+1, numbers.length());
        double currentResult = Double.parseDouble(eachNumber[0]);
        for(int i=1;i<eachNumber.length;i++) {
            String op = blank[i-1];
            if(op==operators[0]) {
                currentResult = currentResult + Integer.parseInt(eachNumber[i]);
            } else if(op==operators[1]) {
                currentResult = currentResult - Integer.parseInt(eachNumber[i]);
            } else if(op==operators[2]) {
                currentResult = currentResult / Integer.parseInt(eachNumber[i]);
            } else if(op==operators[3]) {
                currentResult = currentResult * Integer.parseInt(eachNumber[i]);
            }
        }
        return (currentResult==Integer.parseInt(finalResult));
    }

}
类间隙填充{
私有静态字符串编号;//例如6_5_4=15
私有静态字符串[]blank;//空白处的运算符数组
//其中:
//p=正
//m=负
//d=除法
//t=次
私有静态字符串[]运算符={“p”、“m”、“d”、“t”};
公共静态void main(字符串[]args){
数字=参数[0];
blank=新字符串[number.split(“”).length-1];
if(dfs(0)){//如果找到了解决方案
整数计数=0;
while(number.indexOf(“”)!=-1){
int index=numbers.indexOf(“”);
数字=数字。子字符串(0,索引)+空白[计数]+数字。子字符串(索引+1);
计数++;
}
系统输出打印项次(数字);
}
}
私有静态布尔dfs(int i){
if(i==blank.length){//基本大小写:填入所有空格
返回方程();
}
for(字符串op:运算符){
空白[i]=op;
如果(dfs(i+1)){
返回true;
}
}
blank[i]=“_200;”//恢复到以前的状态
返回false;
}
私有静态布尔方程(){
String[]eachNumber=numbers.substring(0,numbers.indexOf(“=”).split(“”);
字符串finalResult=numbers.substring(numbers.indexOf(“=”)+1,numbers.length());
double currentResult=double.parseDouble(每个编号[0]);

对于(int i=1;ibase案例:可能是所有赋值运算符?我不确定这里是否需要递归。考虑到当前计算机的速度,您可以使用纯组合方法(并尝试4^5种可能性)@BasileStarynkevitch:但是递归是实现组合搜索的一种自然方式。4^5只有1024位-最多16位应该没有问题。除此之外,你还需要等待相当长的一段时间。出于好奇,你应该为这个问题编写解决方案,还是你只是选择这样做?我可以看到答案在寻找了几秒钟后,我就把它粘住了。