【问题标题】:recursion dilemma递归困境
【发布时间】:2013-01-11 12:45:57
【问题描述】:

我正在尝试创建代码来查找三个用户输入数字的 GCD。我的目标是用输入的数字调用该方法,除以初始化为 1 的 q,仅当余数为零时记录 q,然后确定它是否大于或等于最小数字,如果不是,则增加 q 和召回方法,但如果我想打印出最后记录的最大 q,我做错了什么?我不断收到堆栈溢出错误。

public static int recursiveMethod (int x, int y, int z, int q)
{
    int largestVar; 
    int xRes = x % q;
    int yRes = y % q;
    int zRes = z % q;
    if (xRes==0 && yRes ==0 && zRes==0) {
                largestVar = q;
                if (q >= x && q >= y && q >= z)
                {
                    return largestVar;
                }
    }
    else { 
           q++;
    }
   return recursiveMethod(x, y, z, q);

【问题讨论】:

  • 递归次数是有限制的,这受堆栈深度的限制。所以我建议你检查你的算法,如果有必要把它变成一个迭代算法

标签: java


【解决方案1】:

我注意到的一个错误,你的 if 条件是错误的:

if (q >= x && q >= y && q >= z)

这3个数的GCD都小于等于每一个,所以改成:

if (x >= q && y >= q && z >= q)

如果你像这样迭代地测试数字,你应该从某个数字开始倒计时,这样你就可以保证满足条件的数字就是实际的 GCD。并且该特定起始数字必须是最少 3 个数字。 您的方法的完整工作版本在这里:

public static int recursiveMethod(int x, int y, int z, int q) 
{
    int largestVar;
    int xRes = x % q;
    int yRes = y % q;
    int zRes = z % q;
    if (xRes == 0 && yRes == 0 && zRes == 0) {
        largestVar = q;
        if (x >= q && y >= q && z >= q) {
            return largestVar;
        }
    } else {
        q--;
    }
    return recursiveMethod(x, y, z, q);
}

示例调用:

int x = recursiveMethod(30, 60, 45, 30); // x = 15 after this execution.

【讨论】:

  • 我把 && 改成了 ||为此,它工作正常!但是,现在我正在为“xRes”获取stackoverflow
  • 哦,我明白了。我要解决这个问题的方式使事情变得更加复杂。因为我需要这个程序来处理任何随机输入的数字。
  • 注意:如果 q 被初始化为 min(x,y,z) 并递减,if (x >= q && y >= q && z >= q) 肯定为真。可以删除 if 块并简单地返回那里。
  • @femtoRgon 您忽略了外部 if-block。 recursiveMethod(30, 60, 45, 30) 返回 15 是正确的。
  • 它得到了绝对正确的答案,但是内部的 if 块是微不足道的,而且没有必要。当xRes == 0 && yRes == 0 && zRes == 0你有正确答案时,通过这个迭代,可以立即返回一个值。
【解决方案2】:

不要忘记 gcd(x, y, z) = gcd(gcd(x, y), z). 所以,如果你想要一个更简单的算法,你可以用两个数字实现 gcd,然后为 3 个数字调用该方法。

public static int GCD(int x, int y) {
   if (y == 0) return x;
   return GCD(x, x % y);
}

然后是三个数字:

public static int GCDfor3 (int x, int y, int z) {
    return GCD(GCD(x, y), z)
}

【讨论】:

    【解决方案3】:

    您的第一种情况是 1,此时xRes==0 && yRes ==0 && zRes==0 肯定为真,并且您将 maximumVar 设置为 1。然后,由于 1 可能小于传入的变量,它会继续,不会在else 阻塞,并再次使用 q=1 调用recursiveMethod!这个过程会不断重复。

    public static int recursiveMethod (int x, int y, int z, int q, int largestVar)
    {
        int xRes = x % q;
        int yRes = y % q;
        int zRes = z % q;
        if (xRes==0 && yRes ==0 && zRes==0) {
        //A common denominator found!
                    largestVar = q;
        }
        //regardless whether a denominator was found, check for the termination condition
        //Or works here, by the way, since we only need to know when q is greater than one of them.
        if (q >= x || q >= y || q >= z) {
            return largestVar;
        }
        //if we don't terminate, increment q and recurse. 
        q++;
        return recursiveMethod(x, y, z, q, largestVar);
    }
    

    修改为正确处理最大变量。没注意那一点。作为局部作用域,最大变量的值不会通过递归调用来维护,因此它也必须传递到 recursiveMethod 调用中(或者被声明为类作用域变量,等等)。一个合适的起始值是 0。

    【讨论】:

    • 谢谢!我实际上尝试了这段代码,但每次我尝试编译它时,我都会不断收到“变量最大变量可能没有被初始化”。我还得到了一个“缺少返回语句”,它应该放在方法中,但在 if/else 语句之外
    • 修改为正确处理largestVar。当时并没有真正考虑过它的这方面。
    【解决方案4】:

    如果您每次将 Q 递增 1,使用合适的数字,您总是会用完堆栈。我会对每对数字使用欧几里得算法,然后从那里开始。我的意思是,如果它在 a、b、c 之间是共同的,那么它必须是 a 和 b 或 a 和 c 或 c 和 b 之间的公因数,对吧?

    https://math.stackexchange.com/questions/85830/how-to-use-the-extended-euclidean-algorithm-manually

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-16
      • 1970-01-01
      • 2016-10-14
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      相关资源
      最近更新 更多