递归地获取Javascript中一组数字的所有可能组合

时间:2013-09-14 05:42:06

标签: javascript recursion

我有一个javascript应用程序,我需要对数字0到6的每个可能组合进行测试,而不复制组合中的任何数字。

所以: 0123456, 0123465, 0123546, 0123564 ...

(但是,例如,不应包括0123455,因为5是重复的)

我已经迭代地完成了它:

function testAllCombinations(){
    for(var i = 0; i < 7; i++){
        for(var j = 0; j < 7; j++){
            if(j == i)
                continue;
            for(var k = 0; k < 7; k++){
                if(k == j || k == i)
                    continue;
                for(var l = 0; l < 7; l++){
                    if(l == k || l == j || l == i)
                        continue;
                    for(var m = 0; m < 7; m++){
                        if(m == l || m == k || m == j || m == i)
                            continue;
                        for(var n = 0; n < 7; n++){
                            if(n == m || n == l || n == k || n == j || n == i)
                                continue;
                            for(var o = 0; o < 7; o++){
                                if(o == n || o == m || o == l || o == l || o == j || o == i)
                                    continue;

                                runTest(i, j, k, l, m, n, o);
                            }
                        }
                    }
                }
            }
        }
    }
}

并且它工作正常,但我想以递归方式进行,并且我很难构建算法。

有人可以给我一些方向吗?

提前致谢。

2 个答案:

答案 0 :(得分:4)

这看起来像关于递归的一般问题。

递归算法可以分为两部分,一个基本案例和一个递归案例。 首先,弄清楚基本情况,这导致一个微不足道的结果,不需要递归。可能有多个输入导致基本情况。从最琐碎的输入开始,然后从那里扩展。 很快,您将发现递归情况,这是递归函数的关键因素。您会发现递归案例都可以使用由先前案例组成的类似模式来解决,包括基本案例。

所以对于这个问题,假设用户可以输入一个字符串,并且你想打印字符串中的所有字符组合,让我们调用这个调用f(s)。 如果用户输入长度为0或1的字符串,则只返回提供的字符串,因为只有一个组合可用。这里没什么特别的。这是基本情况。

如果用户输入长度为2的字符串(例如“01”),很明显可能的组合是“01”和“10”。 你是怎么得到这个答案的? 注意“01”=“0”+“1”和“10”=“1”+“0” 哇,我们循环遍历每个数字并将其与f(s)的结果相结合,其中s =剩余数字 即。 “01”=“0”+ f(“1”)和“10”=“1”+ f(“0”)。
我们已经知道如何在长度为1时解决这个问题,所以现在我们知道如何在输入长度为2时解决问题。

现在如果输入长度是3(例如“012”),你知道答案是“012”,“021”,“102”,“120”,“201”,“210”。
注意“012”,“021”=“0”+“12”,“0”+“21”和“102”,“120”=“1”+“02”,“1”+“20”,和“201”,“210”=“2”+“01”,“2”+“10” 哇,我们循环遍历每个数字并将其与f(s)的结果相结合,其中s =剩余数字。 听起来很熟悉?
即。 “012”,“021”=“0”+ f(“12”)和“102”,“120”=“1”+ f(“02”)和“201”,“210”=“2”+ F( “10”)
我们已经知道如何在长度为2时解决这个问题,所以现在我们知道如何在输入长度为3时解决问题。

你现在看到了这种模式吗? 在每个级别(输入的长度),我们应用相同的原则,因此可以在问题的子集上反复使用相同的代码片段,最终将它们组合在一起以形成最终答案。这就是使递归如此优雅的原因。

注意当输入长度为4时,我们可以再次应用相同的模式 即。 f(“0123”)=“0”+ f(“123”),“1”+ f(“023”),“2”+ f(“013”),“3”+ f(“012”) ,当长度为3时,我们已经知道如何解决这个问题,所以现在我们知道如何在输入长度为4时解决问题。

我可以继续,并在代码中写出解决方案,但毫无疑问,有更好的资源用于学习递归,所以我会让你自己寻找它们。 但是,(我希望)我的解释足以让你思考正确的方向,甚至可以解决你的问题,而不必阅读任何额外的资源。

请记住,解决递归问题的关键是从最简单的情况开始,然后从那里开始构建。

答案 1 :(得分:0)

您可能需要查看按字典顺序生成 next 排列的the following algorithm

在传递给生成算法之前,必须按升序对初始数组进行排序。

  

以下算法在给定排列后按字典顺序生成下一个排列。它就地改变了给定的排列。

     
      
  1. 找到k这样的最大索引a[k] < a[k + 1]。如果不存在这样的索引,则排列是最后的排列。
  2.   
  3. 找到最大的索引l,使a[k] < a[l]
  4.   
  5. a[k]的值与a[l]
  6. 的值互换   
  7. 将序列从a[k + 1]反转至最终元素a[n]
  8.