试图将嵌套循环转换为递归函数

时间:2015-08-13 04:42:48

标签: javascript recursion

我正在尝试创建以下嵌套循环的递归版本,并获得与参考代码相同的结果。示例如下。

这是Codepen http://codepen.io/anon/pen/XbQMLv

上的一个版本

(代码的目的是仅输出索引中唯一的整数组合。)

原始代码和输出:

var len = 4;

for (var a = 0; a < len; a++) {
  for (var b = a + 1; b < len; b++) {
    for (var c = b + 1; c < len; c++) {
      console.log(a, b, c);
    }
  }
}
// Outputs:
// 0 1 2
// 0 1 3
// 0 2 3
// 1 2 3

递归代码和输出:

var len = 4;
var end = 3;
var data = [];

var loop = function (index) {
  if (index === end) {
    console.log(data);
    return;
  }
  for (var i = index; i < len; i++) {
    data[index] = i;
    loop(i + 1);
  }
}

loop(0);
// Outputs:
// [ 0, 1, 2 ]
// [ 0, 2, 3 ]
// [ 1, 3, 2 ]
// [ 2, 3, 3 ]

不确定我在这里缺少什么。

4 个答案:

答案 0 :(得分:3)

您的代码中只有一个小错误:

您从i + 1调用递归函数,而不是index + 1 它导致index等于当前数组索引,但它的值是。

例如,当您通过[0, 1, 2]时,您的数据现在为[0, 1],您即将插入3,即拨打loop(3 + 1)index 4超出阵列范围。 if (index === end)条件失败并且不输出。 for (var i = index; i < len; i++)循环也失败了,一切都出错了。

应该是:

var len = 4;
var end = 3;
var data = [];

var loop = function (index) {
  if (index === end) {
    console.log(data);
    return;
  }
  for (var i = index; i < len; i++) {
    data[index] = i;
    loop(index + 1); // <--- HERE
  }
}

loop(0);

这是工作JSFiddle demo

<强>更新

哦,现在我明白了。您需要a[i] > a[i-1]条件才能适用于所有组合。只需添加start变量即可保存最后插入的值,以符合此规则。

var len = 4;
var end = 3;
var data = [];

var loop = function (start, index) {
  if (index === end) {
    document.body.innerHTML += "<br/>" + data;
    return;
  }
  for (var i = start; i < len; i++) { // We start from 'start' (the last value + 1)
    data[index] = i;
    loop(i + 1, index + 1); // Here, we pass the last inserted value + 1
  }
}

loop(0, 0); // At beginning, we start from 0

Updated JSFiddle demo with passing argument

如果您觉得错误,可以检查以前的值,而不是将值作为参数传递。条件将类似于“如果它是第一个数字,从0开始;否则 - 从前一个数字开始”。

var start = (index === 0 ? 0 : data[index-1] + 1);  

Updated JSFiddle demo with calculating start

答案 1 :(得分:2)

当你有三个for循环时,你必须为递归函数传递2个参数。

var len = 4;
var end = 3;
var data = [];

var loop = function(start, index) {
  if (index === end) {
    console.log(data);
    return;
  }
  for (var i = start; i < len; i++) {
    data[index] = i;
    loop(i + 1, index + 1); //Pass as like a+1 & b+1
  }
}

loop(0, 0);

答案 2 :(得分:2)

有几个错误;您从i+1而不是index+1开始递归,而您从index开始计算而不是从data[index-1]+1开始计算。

更正后的版本是:

var len = 4;
var end = 3;
var data = [];

var loop = function (index) {
  if (index === end) {
    console.log(data);
    return;
  }
  for (var i = (index==0 ? 0 : data[index-1]+1); i < len; i++) {
    data[index] = i;
    loop(index + 1);
  }
}

答案 3 :(得分:0)

输出确切的预期结果。

var len = 4;
var end = 3;
var data = [];

var loop = function(i) {
  if(data.length === end) {
    // console.log(data); -> Wont work in snippet
    
    // Snippet workaround
    document.getElementsByTagName('body')[0].innerHTML += data.join(',') + '<br/>';
    return;
  }

  if(i >= len)
    return;

  data.push(i);
  loop(i + 1);

  data.pop();
  loop(i + 1);
};

loop(0);