以下问题来自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;
答案 0 :(得分:6)
基本上这个功能可以分解为:
如果“start”(数字数组中的当前位置)是数组末尾的一部分(换句话说,如果我们尝试了所有数字),那么如果目标函数成功则该函数成功达到了(即为零)
否则,继续使用包含的当前数字(start+1
)进行迭代(target-nums[start]
),如果可行则返回true
否则,包括当前号码不起作用,因此继续迭代而不使用当前号码。如果可行,请返回true
如果我们已经达到这一点,那么就无法添加有效的数字,所以请返回false
。
您已经分解了所有可能的函数调用的步骤,并且您观察到有一个返回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