【问题标题】:Is this implementation of gcd correctgcd 的这个实现是否正确
【发布时间】:2013-07-11 19:58:09
【问题描述】:
public static int divisor(int m, int n) {
    if (m == 0 || n == 0) {
        return m+n;
    } else {
        return divisor(n, m%n);
    }
}

amazon.interviewstreet.com 中的某些输入(我不知道是哪个,因为他们没有透露他们用于测试用例的输入)给了我错误的答案

还有为什么这个实现总是给我stackoverflow(再次不知道哪些输入)

public static int divisor(int m, int n) {
    if(m == 0 || n == 0) {
        return m+n;
    } else if (m > n) {
        return divisor(n, m%n);
    } else {
        return divisor(m, n%m);
    }
}

请让我知道我错过了什么。我是编程新手,还是个初学者。

【问题讨论】:

  • 给我错误的答案那就错了。
  • `return(m, n%m);`这甚至编译?
  • 很抱歉这是一个打字错误。我已经编辑了这个问题。 @SotiriosDelimanolis 他们没有给我解释哪个特定输入的错误,所以我问哪个可能的输入会产生错误的答案?也许这澄清了我的问题。

标签: java greatest-common-divisor


【解决方案1】:

我认为第一个是编程竞赛的代码。如果是这样,请注意您的数据类型。可能是 'int' 不足以容纳输入。尝试“长”。 (只有当您的算法正确时,这才有效。)

【讨论】:

  • 谢谢你的回答。必须使用 BigInteger 而不是 ints 和 long。
  • 发布您的程序的完整代码。这将有助于了解发生了什么。
  • 这是 link 之前以 stackoverflow 错误结束的代码。
  • @meteors 我错误地将答案添加到主要问题中。检查一下。
【解决方案2】:

我觉得

return(m, n%m);

应该是

return divisor(m, n%m);

【讨论】:

  • 对不起,这只是一个打字错误,无论如何我提交了除数(m,n%m);仅限。
【解决方案3】:

可能对nm 的负值处理无效? 阅读例如这个:Best way to make Java's modulus behave like it should with negative numbers?

【讨论】:

    【解决方案4】:

    第二部分是什么

    返回(m, n%m);

    此代码是否已编译?

    使用:

    public static int divisor(int m, int n) {
    if(m == 0 || n == 0)
        return m+n;
    else if(m>n)
        return divisor(n, m%n);
    else
        return divisor(m, n%m);}
    

    【讨论】:

    • 我已经更改了代码,但是什么输入会导致代码进入无限循环(stackOverFlow)?我无法得到那个。
    【解决方案5】:

    首先,

    return(m, n%m) 
    

    肯定不会编译,我想它应该是

    return divisor(m, n%m);
    

    其次,我猜第二个 sn-p 的问题是处理负数。 因为 A 和 B 与 -A 和 -B 具有相同的 GCD,所以我会添加

    m = Math.abs(m);
    n = Math.abs(n);
    

    到方法的开头

    【讨论】:

      【解决方案6】:

      第二部分:

      还有为什么这个实现总是给我stackoverflow(再次不知道哪些输入)?

      试试这个输入集:

      5 3 1 16 5 10

      它会给你stackoverflow错误。对于您在 pastebin 中的给定代码。

      为什么?

      如果输入是'1'就会出现这个问题。

      编辑您的代码部分,如下所示,查看输入的输出 (1 1)。

      public static int divisor(int m, int n) {
          System.out.println("### "+m+" "+n);
          if (m == 0 || n == 0) {
              return m + n;
          } else if (m > n) {
              return divisor(n, m % n);
          } else {
              return divisor(m, n % m);
          }
      }
      

      在某些方面会是这样的:

      .
      .
      ### 1 1134903170
      ### 1 0
      ### 1 1836311903
      ### 1 0
      ### 1 -1323752223
      ### -1323752223 1
      ### -1323752223 1
      ### -1323752223 1
      .
      .
      

      因为在您的代码中,函数调用如下所示。

         public static int divFib(int num) {
          int i = 1, j = 2, temp;
      
          while (divisor(num, j) == 1) {
              temp = j;
              j = j + i;
              i = temp;
          }
          return j;
         }
      

      divisor(num, j) 将像 divisor(1, 2) 一样被调用,然后下面的部分将执行

      else {
              return divisor(m, n % m);
          }
      

      调用将类似于除数(1,0),因为 n%m = 2%1 =0

      那么 '1' 将返回为 (m+n = 1)。

      然后 while (divisor(num, j) == 1){} 将再次执行并且 'j' 将增加。但是'num'是'1'。同样的事情一次又一次地发生。结果 'j' 是一个巨大的数字,最终它将分配一个负数。 (我想你知道为什么会这样)。

      问题是这永远不会停止。因此堆栈将由于大量的函数调用而溢出。

      我认为这是一个非常清楚的解释,如果您有任何疑问,请询问。 (对不起,我在这里错误地发布了答案。)

      【讨论】:

      • 但这在第一个实现中也应该是问题,那么为什么它没有给出stackoverflow错误?
      • 原因是你的第一个实现函数调用将在 2 调用 max 后返回一个值。但是在您的第二个实现中,它将有大量未返回的函数调用(它们仍在堆栈中,直到从 successors 返回值)。这就是为什么您的第二个 cade 出现堆栈溢出的原因。你的第一个代码可能会给出 TLE 或 WA(以编程竞赛的方式)
      猜你喜欢
      • 1970-01-01
      • 2017-02-03
      • 1970-01-01
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 2018-11-13
      • 1970-01-01
      相关资源
      最近更新 更多