【问题标题】:How does JavaScripts's Recursive OR work?JavaScripts 的递归 OR 是如何工作的?
【发布时间】:2016-11-09 04:37:49
【问题描述】:

问题:数组中的任何数字组合总和是数组的最大数吗?

有一个 Coderbyte 答案,original source,我无法理解。我正在尝试将这个函数形象化,但这对我来说没有意义。这是:

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);
    return recursion(target,array) || recursion(target - n, array);
  }
  return recursion(largest,arr);        
}

因此,给定:

[3,5,-1,8,12]

它应该输出:

"true"

我的解释是,return 语句将调用 || 周围的每个函数,然后调用从这些函数产生的任何函数,等等,直到数组的长度为 0。但是它如何检查最大数的正确加数呢?

【问题讨论】:

标签: javascript arrays recursion


【解决方案1】:

线

  return recursion(target,array) || recursion(target - n, array);

首先调用recursion() 并使用目标总和以及去掉第一个元素的数组。如果返回true(因为target 为零且数组为空),则|| 的右侧将 被调用。只有当第一次调用返回undefinedfalse 时,才会进行右侧调用。

所以整个过程是首先找到最大值,然后使用该值和列表的其余部分调用递归过程。反复地,递归例程撬出第一个值,然后检查列表的其余部分中是否有等于目标的总和,是否有等于目标的总和减去 列表其余部分中的第一个值。

它有助于稍微重新排列函数,以便可以跟踪行为:

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(当target12),给出7 的目标和一个仅包含8 的列表;那也行不通。继续,只有当进程到达原始调用的右侧时,target12n-1,事情才开始查找。因为12 - -11313 - 588 - 80,所以有一组值求和为目标。

【讨论】:

  • 等等,我还是不明白这些总和是如何计算出来的。
  • @pward sums 没有被计算,至少不是直接计算。关键是target - n 的东西。这会导致进程在n 确实 参与时尝试找到一组可能的值;左边是检查n参与的时间。
  • 但是如果n在第一次循环后被剃掉,那么该函数将如何检查数组的所有可能组合?
  • 我必须让它看起来像。我现在感觉就像那句话:“为了理解递归,你必须首先理解递归。”当我弄清楚时,我会写一篇关于它的博客文章并将其发布在这里。感谢您的耐心等待:)
  • 我相信我已经为自己解开了这个谜!经过一些帮助思考后,谜团的症结似乎是“解决零”的求和检查方法,自高中以来我并没有真正使用过。在此处查看 reddit 帖子:reddit.com/r/learnprogramming/comments/4roxb0/…
【解决方案2】:

希望这有助于理解||

true  || 1 // => true
false || 1 // => 1


function returnTrue() {
  return true;
}

function returnFalse() {
  return false
}

returnTrue()   || 1 // => true
returnFalse()  || 1 // => 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-19
    • 2013-03-20
    • 2012-10-04
    • 2011-01-25
    • 1970-01-01
    • 2013-03-09
    • 2013-07-06
    相关资源
    最近更新 更多