【问题标题】:Writing a recursive function which iterates through an unknown depth of nested loops编写一个遍历未知深度的嵌套循环的递归函数
【发布时间】:2013-04-11 14:52:03
【问题描述】:

给定一个值数组:

var values = new Array(); 

array.push(2);
array.push(3);
array.push(4); 

我想创建一个迭代函数,它可以为任意长度的数组存储所有可能的值组合。

例如,在这种情况下,可能的值为 (1,1,1)(1,1,2)(1,1,3)(1,1,4)(1,2,1)( 1,2,2)(1,2,3)(1,2,4)(2,1,1)(2,1,2)(2,1,3)(2,1,4)(2 ,2,1)(2,2,2)(2,2,3)(2,2,4)

我知道要做到这一点,我需要使用一个递归函数,如果没有达到最大深度,它将更深一层并再次调用该函数......

我知道从哪里开始(我认为可能)

function iterativeLoop(level, depth) {
    for(var i = 0; i < values.length; i++) {
        if(level < depth) {
            iterativeloop(level+1, depth);
        }
        else if (level=depth) {
        }
   }
}

我不确定一旦函数被调用得更深,我如何才能访问“上层”……也就是说,我不确定如何访问 (1,2,4) 而不仅仅是 (?,? ,4)

我希望这是有道理的?

(对不起,我知道我的标题不太好,我想不出如何简洁地解释它)

【问题讨论】:

  • 您要查找的词是“递归”,而不是“迭代”(如果您正在搜索,可能会有所帮助)。如果我有时间,我会写一个例子。
  • 另外,可能没有必要。现在写一个答案。
  • 你从来没有真正编写递归函数。
  • 第一段代码意味着 var values = [2, 3, 4]; 或者我错过了什么?
  • 我仍然想知道1 来自哪里=/

标签: javascript recursion iteration


【解决方案1】:

我不确定一旦函数被调用得更深,我如何才能访问“上层”……也就是说,我不确定如何访问 (1,2,4) 而不仅仅是 (?,? ,4)

您需要传递它们,例如在一个数组中。

for(var i = 0; i < values.length; i++)

这不应该是要执行的外部迭代,除非您想在一个简单的嵌套循环中构造一个二维结果数组(见下文)。相反,您希望 value.length 成为您递归的深度。在每个递归级别上,您将从 1 迭代到 values[level] 然后。而不是传递level,我们将传递一个当前状态的数组(上面的问号),其长度是级别。

var values = [2,3,4];
function recurse(state) {
    var level = state.length;
    var depth = values.length;
    if (level == depth) {
        console.log.apply(console, state); // or whatever you want to do
    } else {
        for (var i=1; i<=values[level]; i++) {
            state.push(i); // save current question mark
                           // notice state.length = level + 1 now
            recurse(state); // enter next level
            state.pop(); // delete it after we're so state doesn't grow infinitely :-)
        }
    }
}
recurse([]);

如果您想对值使用迭代,您可以通过向结果数组添加越来越多的状态(每级增长一个值)来实现,最终将包含所有可能的组合:

var values = [2,3,4];
var result = [[]]; // one empty state at level 0
for (var i=0; i<values.length; i++) {
    var reslen = result.length,
        val = values[i];
    var mult = []; // will become the new result with a length of (reslen * val)
    for (var j=0; j<reslen; j++) {
        for (var k=1; k<=val; k++) {
            var state = result[j].slice(); // make a copy
            state.push(k);
            mult.push(state);
        }
    }
    result = mult;
}

// logging the `result` on each level will show us
// 0 - [[]]
// 1 - [[1],[2]]
// 2 - [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3]]
// 3 - [[1,1,1],[1,1,2],[1,1,3],[1,1,4],[1,2,1],[1,2,2],[1,2,3],[1,2,4],[1,3,1],[1,3,2],[1,3,3],[1,3,4],[2,1,1],[2,1,2],[2,1,3],[2,1,4],[2,2,1],[2,2,2],[2,2,3],[2,2,4],[2,3,1],[2,3,2],[2,3,3],[2,3,4]]

您可以看到这与@Jason 的方法有何相似之处。

【讨论】:

    【解决方案2】:

    您不需要递归,因为任意数据集的长度是在运行时开始时定义的:

    var numbers = [2,3,4];
    var result_array = [];
    var num_product = 1;
    var i=0, j=0, k=0; // iterators
    
    for (i=0; i<numbers.length; i++) {
        num_product *= numbers[i];
    }
    for (i=0; i<num_product; i++) {
        result_array.push([]);
    }
    for (i=0; i<result_array.length; i++) {
        product = 1;
        for (j=0; j<numbers.length; j++) {
            k = (Math.floor(i/product)%numbers[j]) + 1;
            product *= numbers[j];
            result_array[i][j] = k;
        }
    }
    

    针对任意数量的数组元素进行了测试和功能。

    A side-by-side benchmark 显示此代码比递归代码快得多 - 如果您能够避免递归(例如,您预先知道足够的信息来定义整个问题)然后最好这样做,并且当前定义的问题允许您这样做。如果您只是想学习递归,那么这对您没有太大帮助:)

    【讨论】:

    • 递归哪里去了^^
    • 正如我对原始问题的评论,我认为这更适合非递归方法,我的印象是他并不要求它是递归的,他只是认为有必要.不幸的是,我有点仓促,我认为我的解决方案无论如何都不能正常工作。等我有空再回来看看。
    • 我确实需要它,正如我发布的那样,我希望它适用于 任何 长度的数组。 3 长度数组只是一个示例。
    • 我修正了算法,它适用于任何长度的数组,你不需要递归。
    猜你喜欢
    • 2023-04-01
    • 2015-11-17
    • 1970-01-01
    • 2021-11-05
    • 2019-08-03
    • 1970-01-01
    • 2014-06-29
    • 2019-01-20
    • 1970-01-01
    相关资源
    最近更新 更多