线
return recursion(target,array) || recursion(target - n, array);
首先调用recursion() 并使用目标总和以及去掉第一个元素的数组。如果返回true(因为target 为零且数组为空),则|| 的右侧将不 被调用。只有当第一次调用返回undefined 或false 时,才会进行右侧调用。
所以整个过程是首先找到最大值,然后使用该值和列表的其余部分调用递归过程。反复地,递归例程撬出第一个值,然后检查列表的其余部分中是否有等于目标的总和,或是否有等于目标的总和减去 列表其余部分中的第一个值。
它有助于稍微重新排列函数,以便可以跟踪行为:
function ArrayAdditionI(arr) {
arr.sort(function(a,b){
return a - b;
});
var largest = arr.pop();
function recursion(target,array){
if(array.length === 0){
return target === 0;
}
var n = array[0];
array = array.slice(1);
console.log("target: " + target + " n: " + n);
var r1 = recursion(target,array), r2 = recursion(target - n, array);
console.log("(" + target + ", " + n + ") left: " + r1 + " right: " + r2);
return r1 || r2;
}
return recursion(largest,arr);
}
如果你用示例数组调用它:
ArrayAdditionI([3,5,-1,8,12]);
您会得到以下跟踪:
target: 12 n: -1
target: 12 n: 3
target: 12 n: 5
target: 12 n: 8
(12, 8) left: false right: false
target: 7 n: 8
(7, 8) left: false right: false
(12, 5) left: false right: false
target: 9 n: 5
target: 9 n: 8
(9, 8) left: false right: false
target: 4 n: 8
(4, 8) left: false right: false
(9, 5) left: false right: false
(12, 3) left: false right: false
target: 13 n: 3
target: 13 n: 5
target: 13 n: 8
(13, 8) left: false right: false
target: 8 n: 8
(8, 8) left: false right: true
(13, 5) left: false right: true
target: 10 n: 5
target: 10 n: 8
(10, 8) left: false right: false
target: 5 n: 8
(5, 8) left: false right: false
(10, 5) left: false right: false
(13, 3) left: true right: false
(12, -1) left: false right: true
所以|| 的左侧表示查看是否可以在不考虑其中一个值的情况下找到总和的方法,而右侧则考虑是否可以找到假设其中一个值的总和是成分之一。从前几行中,您会看到递归跳过前四个值,从小到大,直到最后一次调用的数组为空。目标值仍然是12,所以不起作用。
然后尝试包含值5(当target 是12),给出7 的目标和一个仅包含8 的列表;那也行不通。继续,只有当进程到达原始调用的右侧时,target 为12 和n 为-1,事情才开始查找。因为12 - -1是13,13 - 5是8,8 - 8是0,所以有一组值求和为目标。