【问题标题】:return number of solutions to the equation x1 + x2 + x3 = num返回方程 x1 + x2 + x3 = num 的解数
【发布时间】:2021-05-02 15:02:20
【问题描述】:

我正在尝试编写一个递归方法,它接受一个正整数 num 参数并返回方程的解数

x1 + x2 + x3 = 数量

当三个 x 都是 1 到 10 之间的正整数时。 该方法还应该打印出这些解决方案,每个解决方案在单独的行中。打印顺序无关紧要。

我试过了:

public static int solutions (int x1, int x2, int x3, int counter, int num)
{
    if(x1 > 10 || x2 > 10 || x3 > 10) {
        return 0;
    }
    if (x1 + x2 + x3 == num) {
        System.out.println(x1 + "+" + x2 + "+" + x3);
        counter = 1;
    } else {
        return solutions (x1 + 1, x2, x3, counter, num) +
               solutions (x1, x2 + 1, x3, counter, num) +
               solutions (x1, x2, x3 + 1, counter, num);
    }
    return counter;
}

public static int solutions (int num)
{
    if (num < 3 || num > 30) {
        return 0;
    }
    return solutions (1, 1, 1, 0, num);

}

问题是我重复结果,问题是我得到重复结果,例如num = 5,我得到:

3 + 1 + 1
2 + 2 + 1
2 + 1 + 2
2 + 2 + 1
1 + 3 + 1
1 + 2 + 2
2 + 1 + 2
1 + 2 + 2
1 + 1 + 3

代替

1 + 1 + 3
1 + 2 + 2
1 + 3 + 1
2 + 1 + 2
2 + 2 + 1
3 + 1 + 1

如何避免重复两次?

【问题讨论】:

  • 只打印x1 &lt;= x2 &lt;= x3的解决方案。
  • 请注意,您不必搜索x3 的所有值:从num - x1 - x2 计算它,如果该值超出1..10 范围,则拒绝。
  • 假设你有foo(int a, int b){if (a&lt;3 &amp;&amp; b&lt;3){ foo(a+1, b); foo(a, b+1); }。当您调用foo(1,1) 时,它将在内部调用foo(2,1),然后是foo(1,2)。现在foo(2,1) 将生成对foo(3,1); foo(2,2) 的调用和foo(1,2)foo(2,2); foo(1,3) 的调用。如您所见,foo(2,2) 被调用 两次。您需要决定哪些调用是不需要的。在什么情况下应该和不应该调用foo(2,2)
  • 这是开放大学作业中的一道题,Introduction to computer science using java course

标签: java recursion


【解决方案1】:

这是我的处理方法:

public static void main(String[] args) {
    System.out.println("Number of solutions: "+ solutions(5));
}

public static int solutions(int num) 
{
    if (num < 3 || num > 30)
        return 0;
    else
        return solutions(num, 1, 1, 1);
}

private static int solutions(int num, int x1, int x2, int x3)
{   
    int valid = 0;          
    if (x1 + x2 + x3 == num)
    {
        valid = 1;
        System.out.println(x1 + " + " + x2 + " + " + x3 + " = " + num);            
    }                
    if ((x3 < 10) && (x1 + x2 + x3 < num))
    {
        return valid + solutions(num, x1, x2, ++x3);
    }
    else if ((x2 < 10) && (x1 + x2 < num)) 
    {
        return valid + solutions(num, x1, ++x2, 1);    
    }
    else if ((x1 < 10) && (x1 < num))
    {
        return valid + solutions(num, ++x1, 1, 1);
    }  
    else
    {
        return valid;
    }
}

【讨论】:

  • 这有点晚了,但我可能会建议进行优化:将else if ((x2 &lt; 10) &amp;&amp; (x1 + x2 &lt; num)) 替换为else if ((x2 &lt; 10) &amp;&amp; (x1 + x2 + 1 &lt; num)),将else if ((x1 &lt; 10) &amp;&amp; (x1 &lt; num)) 替换为else if ((x1 &lt; 10) &amp;&amp; (x1 + 2&lt; num)),以防止冗余递归调用。例如,如果 num=5 4 不需要调用 1+4+1、4+1+1、3+2+1 和 2+3+1。
【解决方案2】:

这绝对是您提供的代码的预期行为;第一次调用你的函数时,它将执行此操作(为简洁起见,我删除了最后两个参数):

return solutions(2, 1, 1) + solutions(1, 2, 1) + solutions(1, 1, 2)

鉴于您将所有三个参数都加 1 直到达到 10,您会期望(例如)2 + 2 + 1 在某个时候由第一次和第二次调用产生。

您的问题的一个解决方案是通过递归传递某种集合对象,每次找到一个时您都添加解决方案。然后,当您找到一个新的时,您会检查是否包含在您的收藏中,并检查它是否加起来是正确的数字。

【讨论】:

    【解决方案3】:

    这就是我想出的……(它适用于方程中的任意数量的变量)

    public static int solutions(int num)
    {
        return solutions(num, 3, 1, ""); // 'varsInTheEq' represents the numbers of varibelas in the equation (in this case: 'x1 + x2 + x3 = num' which is 3)
    }
    
    private static int solutions(int num, int varsInTheEq, int value, String builder)
    {
        if (num == 0 && varsInTheEq == 0) // if we solved the equation
        {
            System.out.println(builder);
            return 1;
        }
    
        if (varsInTheEq == 0 || value > num)
            return 0;
    
        int r1 = solutions(num - value, varsInTheEq - 1, 1, builder + value + " ");
        int r2 = solutions(num, varsInTheEq, value + 1, builder);
    
        return r1 + r2;
    }
    

    【讨论】:

      猜你喜欢
      • 2019-10-17
      • 2015-06-04
      • 2018-09-24
      • 1970-01-01
      • 1970-01-01
      • 2016-02-04
      • 1970-01-01
      • 1970-01-01
      • 2020-01-28
      相关资源
      最近更新 更多