了解递归如何与多个返回一起使用

时间:2013-08-03 04:28:06

标签: recursion

以下问题来自codingbat:给定一个整数数组,是否可以选择一组整数的组,以便该组与给定目标相加?

该网站的作者提供了以下解决方案:

public boolean groupSum(int start, int[] nums, int target) {
  if (start >= nums.length) return (target == 0);
  if (groupSum(start + 1, nums, target - nums[start])) return true;
  if (groupSum(start + 1, nums, target)) return true;
  return false;
}

假设我想尝试以下情况,其中nums = [2,4,8]并且称为groupSum(0,nums,10)。

我看到groupSum(0,nums,10)会调用groupSum(1,nums,10)groupSum(1,nums,8)

groupSum(1,nums,10)来电groupSum(2, nums,10)groupSum(2, nums,6)

groupSum(1,nums,8)来电groupSum(2,nums,8)groupSum(1,nums,4)

等...

通过代码我看到以下调用:

groupSum(3,nums,10)
groupSum(3,nums,2)
groupSum(3,nums,6)
groupSum(3,nums,-2)
groupSum(3,nums,8)
groupSum(3,nums,0)
groupSum(3,nums,4)
groupSum(3,nums,-4)

我看到groupSum(3,nums,0)因为第一行而应该返回true:
if (start >= nums.length) return (target == 0);但我对其他电话如groupSum(3,nums,-4)感到困惑。从第一行开始,它应该明显导致target != 0以来的错误。

也有人可以解释为什么在

中需要返回真实陈述
if (groupSum(start + 1, nums, target - nums[start])) return true;

我认为第一行会判断为真还是假。

if (groupSum(start + 1, nums, target)) return true;

2 个答案:

答案 0 :(得分:6)

基本上这个功能可以分解为:

  1. 如果“start”(数字数组中的当前位置)是数组末尾的一部分(换句话说,如果我们尝试了所有数字),那么如果目标函数成功则该函数成功达到了(即为零)

  2. 否则,继续使用包含的当前数字(start+1)进行迭代(target-nums[start]),如果可行则返回true

  3. 否则,包括当前号码不起作用,因此继续迭代而不使用当前号码。如果可行,请返回true

  4. 如果我们已经达到这一点,那么就无法添加有效的数字,所以请返回false

  5. 您已经分解了所有可能的函数调用的步骤,并且您观察到有一个返回true(目标为零的那个)。此true结果将递归备份为最终返回值。

    以下是其工作原理的粗略细分:

    groupSum(0,[2,4,8],10)
    0 >= 3? no, so continue:
    groupSum(1,[2,4,8],10-2)?
      1 >= 3? no, so continue:
      groupSum(2,[2,4,8],8-4)?
        2 >= 3? no, so continue:
        groupSum(3,[2,4,8],4-8)?
          3 >= 3? yes. -4 == 0? no, return false
        groupSum(3,[2,4,8],4)?
          3 >= 3? yes. 4 == 0? no, return false
        return false
      groupSum(2,[2,4,8],8)?
        2 >= 3? no, so continue:
        groupSum(3,[2,4,8],8-8)?
          3 >= 3? yes. 0 == 0? yes, return true
        yes, return true
      yes, return true
    yes, return true
    

    希望这有帮助!

答案 1 :(得分:2)

除了Kolink的详细介绍,为了它的价值,在Java中,我创建了这个来帮助我看到:

public class TestRecursion{

    public static boolean groupSum(int start, int[] nums, int target, String s) {
        System.out.println(new String(new char[start]).replace("\0", "    ")+"start="+start+" target="+target+" parent="+s);
        if (start >= nums.length) return (target == 0);
        if (groupSum(start + 1, nums, target - nums[start], "A:"+start+"_"+target)) return true;
        if (groupSum(start + 1, nums, target, "B:"+start+"_"+target)) return true;
        return false;
    }

    public static void main(String... args){
        int[] nums = {2,4,8};
        groupSum(0, nums, 10, "");
    }
}

输出:

start=0 target=10 parent=
    start=1 target=8 parent=A:0_10
        start=2 target=4 parent=A:1_8
            start=3 target=-4 parent=A:2_4
            start=3 target=4 parent=B:2_4
        start=2 target=8 parent=B:1_8
            start=3 target=0 parent=A:2_8