【问题标题】:"too much recursion" variations with repetitions重复的“太多递归”变化
【发布时间】:2014-11-07 17:21:44
【问题描述】:

我正在尝试创建一个函数,列出所有可能的重复变化。 我所做的返回“递归过多”。

function variants(amount, chars, junk){
    var junkarray = junk.split(",");
    var newjunk;
    if(junkarray[junkarray.length-1]==amount){
        newjunk = ",";
    }
    if(junk.length==Math.pow(chars.length, amount)){
        console.log(junk);
        return;
    }else{
        for(var i = 0; i < chars.length; i++){
            variants(amount, chars, junk+newjunk+chars[i]);
        }
    }
}
variants(3, ["1", "2"],"");

【问题讨论】:

  • 你的 sn-p 让我的标签崩溃了。我认为你应该删除它
  • :D 是的,你是一个专业的tabcrasher。如果它抛出“太多递归”,为什么要制作一个可运行的 sn-p?
  • 你能解释一下预期的输入/输出应该是什么吗?
  • 由于此代码不起作用,您能描述一下预期的输出吗? “所有可能的重复变化”有点太模糊了。
  • 您是否尝试返回类似 ["1,1,1", "1,1,2", "1,2,1", "1,2,2", "2 ,1,1", "2,1,2", "2,2,1", "2,2,2"]?

标签: javascript recursion combinatorics


【解决方案1】:

你的问题是你从来没有碰到你的退出子句,你得到了一个无限递归。你的问题在这里:

var newjunk;
...
variants(amount, chars, junk+newjunk+chars[i]);

您没有将newjunk 初始化为任何内容,因此当它跳过有可能设置它的部分时,您的变量仍然未定义。因此,当您将字符串连接到 else 子句中的其他变量时,发生的事情是 js 将值“未定义”转换为“未定义”字符串。对于测试剪切粘贴此行:

var newjunk; var junk = ""; var chars = ["1","2"]; console.log(result, junk+newjunk+chars[0]); 

进入您最喜欢的控制台。注意它打印出undefined1。修复它的方法是将newjunk初始化为一个空字符串:

var newjunk = ""

这是更改的jsfiddle

调试递归问题的一个好方法是拿出一张纸和笔,对代码的每一行进行物理跟踪,以确保您的退出子句被命中。您还可以以全局计数变量的形式添加过早退出条件,您可以在函数内递增。当此计数变量达到特定值时,退出。

【讨论】:

    【解决方案2】:

    虽然 Ingo Bürk 的回答确实解释了您遇到无限递归的原因,但它解决了一个稍微不同的问题。这是一种似乎可行的解决方案 (Fiddle):

    var variants = function(amount, chars, soFar) {
        soFar = soFar || [""];
        if (amount === 0) {return soFar;}
        var partials = soFar.map(function(partial) {
            return chars.map(function(char) {
                return partial.concat(char);
            });
        }).reduce(function(a, b) {return a.concat(b);}, []);
        return variants(amount - 1, chars, partials);
    };
    
    var v = variants(3, ["1", "2"]);
    //=> ["111", "112", "121", "122", "211", "212", "221", "222"] 
    

    请注意,对于太大的数据,这也会遇到递归问题,但对于相当小的数据集应该没问题。

    更新

    可能更简洁一点的是不会宣布第三个参数,它应该只在内部用于递归调用,所以 this Fiddle 会更好一点,我认为:

    var variants = function(amount, chars) {
        var soFar = arguments[2] || [""];
        // ... no other changes.
    }
    

    【讨论】:

      猜你喜欢
      • 2016-01-31
      • 2011-11-11
      • 1970-01-01
      • 2020-07-04
      • 2018-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-02
      相关资源
      最近更新 更多