如何理解这种递归

时间:2017-10-16 18:09:18

标签: javascript algorithm recursion dynamic-programming

大家好,我试图理解这个组合总和的解决方案。

 function combinationSum(candidates, target) {
     var result = [];

     if ((candidates == null) || (candidates.length == 0)) {
         return result;
     }

     var cur = [];
     candidates = candidates.sort((a, b) => a - b)
     csh(candidates, target, cur, result, 0);

     return result;
 };

 function csh(cand, target, cur, result, j) {
     //console.log(cur);
     if (target == 0) {
         var temp = cur.slice();
         result.push(temp);
         return;
     }

     for (var i = j; i < cand.length; i++) {
         if (target < cand[i]) {
             return;
         }

         //console.log(cur);
         cur.push(cand[i]);
         console.log(cur);
         csh(cand, target - cand[i], cur, result, i);
         cur.pop();
     }
 }

https://leetcode.com/problems/combination-sum/description/

虽然我理解递归的基本原理,但这个问题在我身上有点丢失了。例如,对于输入:

candidates = [2,3,6,7]
target = 7

当您第一次输入函数cur为空时,我们的第一次迭代是:

[],
[2],
[2,2]

然后我们不断添加cand[i],目前为2

[2,2,2]

但此时,target = 1小于cand[i] 2,我们将返回。自从我们返回后,我们弹出堆栈,从堆栈中弹出最后2。自从我们返回后,我们会增加i,然后我们将3添加到cur

[2,2,3]

由于我们的目标数组等于0,我们现在再次返回并且我的问题是,此时我们一直返回cur为空并继续执行如下函数?

[2,2]
[2]
[]
[6]
[]
[7]

我只是想了解这个功能正在做什么。

2 个答案:

答案 0 :(得分:0)

target对于函数的每次调用都是本地的。 target仅对函数的某些调用是0。请注意,递归调用是:

csh(cand, target - cand[i], cur, result, i);

该范围中的target未更改,但当前输入的csh调用的target值较低。当该函数返回并且程序流重新进入其他级别时,我们继续使用较高的target值,并提供给子查询的减少值target - cand[i]

在将第二个元素更改为下一个元素之前,该算法还将尝试[2,2,...]路径上的所有其他可能性。然后,它会探索[2,3,...]空间和[2,6,...]空间,最终探索所有[3,...][6,...][7,...]种可能性。

算法总是尽可能深(即,尽可能长的数组),但不能超过原始限制。

请注意,它不会产生[2,3,2],因为较早的候选者不能在较晚的候选者之后出现(因此2永远不会在结果中的3之后。它强制执行此操作,使fori = j开始,其中j是最后一个候选使用的数组深度,因此当结果在{{}}结束时1}}候选人,它只考虑n和更高的候选人。这具有实用价值,因为该算法仅返回每个值结果集的一个排列:n[2,2,3]包含相同的值集。

答案 1 :(得分:0)

我完全理解递归可能很难理解和解释,但这是我对它的看法。

  1. 第一次调用csh时,这就是传递的内容

    csh(cand,7,[],[],0)

  2. 现在来自for循环,i = 0,被调用的函数是

    csh(cand,5,[2],[],0)

  3. 来自循环的
  4. i = 0,被调用的函数是

    csh(cand,3,[2,2],[],0)

  5. 来自循环的
  6. i = 0,被调用的函数是

    csh(cand,1,[2,2,2],[],0)

  7. 来自for循环的
  8. target(1) < cand[0](2),所以返回步骤4并从[2,2,2]中弹出最后2个,结果为[2,2]

  9. 来自循环i = 1
  10. ,被调用的函数是

    csh(cand,0,[2,2,3],[],1)

  11. 此处符合target == 0条件。所以,[2,2,3]被推到了结果中。然后再次返回步骤4.从[2,2,3]中弹出3。

  12. 来自循环i = 2,target(3) < cand[2](6),所以返回步骤3.并从[2,2]中弹出2,得到[2]。
  13. 来自循环i = 1
  14. ,被调用的函数是

    csh(cand,2,[2,3],[[2,2,3]],1)

  15. 从循环i = 1target(2) < cand[1](1)返回第9步。

  16. 所以没有...

    基本上,将检查每个组合。

    [2,2,2]
    [2,2,3] --> added to result
    [2,3,3]
    [2,6]
    [2,7]
    [3,3,3]
    [3,6]
    [3,7]
    [6,6]
    [6,7]
    [7] --> added to res