3位数的递归置换

时间:2014-04-20 18:09:15

标签: c# algorithm recursion backtracking recursive-backtracking

我正在努力以递归的方式查找3位数的所有排列。

我厌倦了编制以下排列方法:

    static int a = 1;
    static int b = 2;
    static int c = 3;
    static int aCount;
    static int bCount;
    static int cCount;

    static void perm(int a, int b, int c)
    {

        Console.WriteLine("( {0}, {1}, {2} )", a, b, c); // (1,2,3 )

        if (aCount < 1 && bCount<1 &&cCount<1)
        {
            aCount++;

            perm(a, c, b);
        }
        else
            if (aCount==1 && bCount < 1 && cCount<1)
            {

                bCount++;
                perm(b, a, c);
            }
            else
                if (aCount == 1 && bCount == 1 && cCount < 1)
                 {
                    perm(b,c,a);
                  }
        else
                if (aCount==1 && bCount==1 && cCount < 1)
                {
                    cCount++;
                    perm(c, a, b);  //c b a

                }
               else
                    if (aCount == 1 && bCount == 1 &&  cCount == 1)
                {
                    perm(c, b, a);

                }

            }

我试图覆盖所有案例,每一步都有详细说明,但我仍然得到了蓝色的Stack overflow异常。

我感谢你的贡献,所以感谢你们。

3 个答案:

答案 0 :(得分:3)

你说你正在尝试递归,但所有这些行都出现在你的代码中:

perm(a, c, b)
perm(b, a, c)
perm(b, c, a)
perm(c, a, b)
perm(c, b, a)

当然是函数的第一次调用:perm(a, b, c)

这样做容易得多:

static void perm(int a, int b, int c)
{
    Console.WriteLine("( {0}, {1}, {2} )", a, b, c);
    Console.WriteLine("( {0}, {2}, {1} )", a, b, c);
    Console.WriteLine("( {1}, {0}, {2} )", a, b, c);
    Console.WriteLine("( {1}, {2}, {0} )", a, b, c);
    Console.WriteLine("( {2}, {0}, {1} )", a, b, c);
    Console.WriteLine("( {2}, {1}, {0} )", a, b, c);
}

答案 1 :(得分:0)

首先,这两种情况中的任何一种都会导致无限递归:

if (aCount == 1 && bCount == 1 && cCount < 1)
{
    perm(b,c,a);
}

if (aCount == 1 && bCount == 1 && cCount == 1)
{
    perm(c, b, a);
}

原因是您不能更改aCountbCountcCount,因此您最终会重复触发相同的案例。

除此之外,你似乎并没有真正地递归地思考这个问题 - 正如另一个答案所提到的,所有的排列都出现在一个调用中,所以,如果你让它以这种方式工作,你的递归深度将为2,这可能主要涉及用print语句替换每个递归调用,并具有非递归函数。

对于递归解决方案,尝试考虑一个解决方案,在当前调用中处理单个字符,然后递归到下一个字符。

更详细的解释,如果你无法弄清楚:

  

  • 从第一个角色开始。
  •   
  • 尝试将当前字符与每个剩余字符交换(包括其自身,即不执行任何操作)。
  •   
  • 递归到下一个角色。
  •   
  • 在最后一个字符处,打印出所有字符。

  • 提示 - 将数组和当前索引传递给您的函数。

    答案 2 :(得分:0)

    &#39;我会给你写伪代码:

    permutationABC()
    {
        int n=3;
        array SOL[n]/* 1 if you get the element  otherwise 0 if you don't get the element , the meaning of SOL is that SOL[0] is 1 if we had got 'a' , otherwise 0. It's the same for the others */
        initSolWithAllZero(SOL)
        permRecursive(abc,SOL,0,n);
    }
    
    permRecursive(SOL,i,n)
    {
        if i == n then print(SOL) 
        else
        {
            for k=0 to n
            {
                 if SOL[k] == 0 then
                 {
                      SOL[k]=1 // take 
                      permRecursive(SOL,i+1,n)
                      SOL[K]=0 // don't take ... go back....
                 }
            }
        }
    }
    

    时间为O(n * n!)O(n!)是排列数,O(n)是打印时间。