【问题标题】:CodingBat split53; Confused about the right way to use returnsCodingBat split53;对使用退货的正确方式感到困惑
【发布时间】:2020-02-26 07:22:51
【问题描述】:

我有点困惑为什么我下面的解决方案没有给出正确的答案。我做了一些挖掘,我猜这与通话的工作方式有关?我认为这两种方式都是一样的,但事实并非如此,但我不完全理解我的返回错误。这是我之前做的研究:https://softwareengineering.stackexchange.com/questions/333247/why-does-recursion-return-the-first-call-in-the-stack-and-not-the-last

问题:

给定一个整数数组,是否可以将整数分成两组,使两组的总和相同,并具有以下约束:所有为 5 的倍数的值必须在一组中,并且所有是 3 的倍数(而不是 5 的倍数)的值都必须在另一个中。 (不需要循环。)

例子:

split53([1, 1]) → 真

split53([1, 1, 1]) → 假

split53([2, 4, 2]) → 真

我的回答:

public boolean split53Helper(int start, int [] nums, int group3, int group5){
  if(start >= nums.length){
    return group3 == group5;
  }

  if(nums[start] % 3 == 0 ){
    if (split53Helper(start + 1, nums, group3 + nums[start], group5)){
      return true;
    }
  }

  if(nums[start] % 5 == 0){
    if (split53Helper(start + 1, nums, group3, group5 + nums[start])){
      return true;
    }
  }

  if(split53Helper(start+1, nums, group3 + nums[start], group5))
      return true;

  if(split53Helper(start+1, nums, group3, group5 + nums[start]))
      return true;

  return false;
}

正确的解决方案:

public boolean split53(int[] nums) {
    return split53Helper(0, nums, 0, 0);
}

public boolean split53Helper(int start, int[] nums, int mult5, int mult3) {
    if(start >= nums.length)
        return mult5 == mult3;

    if(nums[start] % 5 == 0)
        return split53Helper(start+1, nums, mult5 + nums[start], mult3);

    if(nums[start] % 3 == 0)
        return split53Helper(start+1, nums, mult5, mult3 + nums[start]);

    if(split53Helper(start+1, nums, mult5 + nums[start], mult3))
        return true;

    if(split53Helper(start+1, nums, mult5, mult3 + nums[start]))
        return true;

    return false;
}

我的代码没有返回最后一次调用吗? 如果是这样,我什么时候会使用一种方法来返回另一种方法?如果已经有详尽的解释,请告诉我。我以为我了解堆栈和函数调用是如何工作的,但现在我担心我正朝着错误的方向前进。

【问题讨论】:

  • split53 试图解决什么问题?
  • 对不起,我添加了问题

标签: java recursion function-call


【解决方案1】:

这是正确的解决方案,已重写以看起来更类似于您的答案:

public boolean split53Helper(int start, int [] nums, int group3, int group5){
  if(start >= nums.length){
    return group3 == group5;
  }

  if(nums[start] % 3 == 0 ){
    if (split53Helper(start + 1, nums, group3 + nums[start], group5)){
      return true;
    } else {
      return false; // <-------
    }
  }

  if(nums[start] % 5 == 0){
    if (split53Helper(start + 1, nums, group3, group5 + nums[start])){
      return true;
    } else {
      return false; // <-------
    }
  }

  if(split53Helper(start+1, nums, group3 + nums[start], group5))
      return true;

  if(split53Helper(start+1, nums, group3, group5 + nums[start]))
      return true;

  return false;
}

现在您应该看到您的答案与正确解决方案有何不同。如果第一个递归调用返回 false,您的答案将继续调用第三个和第四个递归调用,而正确的解决方案不会。

当递归方法处理数组时,它几乎总是遵循“对一个元素做某事,然后(递归地)对其余元素做这件事”的模式。递归调用询问“数组的其余部分是否可以分为两组,总和相同......?”。

当一个元素可以被 3 整除时,你将它放在 3 的组中并问同样的问题,因此调用:

split53Helper(start + 1, nums, group3 + nums[start], group5)

如果这个问题的答案是“否”,那么您不应该问“如果我把它放在 5 组中会怎样?” (我指的是你答案中的第 4 个递归调用)

split53Helper(start + 1, nums, group3, group5 + nums[start])

你不能把它放在 5 的组中,因为已知元素可以被 3 整除。

这就是为什么当你知道它可以被 3 整除时你应该立即返回,而其余的不能分组。

【讨论】:

    【解决方案2】:

    请在下面找到正确解决方案的说明。
    我认为,解决方案是扫描存储在 nums 中的数字并检查它是否可被 3 或 5 整除,或者它们都不能。

    如果它可以被 3 整除,则将其添加到 group3 并移动到下一个数字。
    如果它可以被 5 整除,则将其添加到 group5 并移至下一个数字。
    如果它不能被任何整数整除,请尝试将两者相加并继续下一个数字 扫描完所有数字后,检查 group3 是否等于 group5

    public boolean split53Helper(int start, int [] nums, int group3, int group5){
          if(start >= nums.length){
            return group3 == group5;
          }
    
          if(nums[start] % 3 == 0 ){
             /**
              * In this case you dont have any choice as the number is divisble by 3.
              * You should add the number to group3 and move on with next number.
              * Dont put the below statement in if condition
              */
            return split53Helper(start + 1, nums, group3 + nums[start], group5);
          }
    
          if(nums[start] % 5 == 0){
            /**
              * In this case you dont have any choice as the number is divisble by 5.
              * You should add the number to group5 and move on with next number.
              * Dont put the below statement in if condition
              */
            return split53Helper(start + 1, nums, group3, group5 + nums[start]);
          }
    
          // Here you have choice, you can either put the number in group3 or group5
    
          if(split53Helper(start+1, nums, group3 + nums[start], group5))
              return true;
    
          if(split53Helper(start+1, nums, group3, group5 + nums[start]))
              return true;
    
          return false;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-03
      • 2015-11-29
      • 1970-01-01
      • 1970-01-01
      • 2018-10-20
      • 1970-01-01
      • 2012-08-24
      相关资源
      最近更新 更多