18

我正在学习回溯和递归,我被困在一种用于打印字符串所有排列的算法中。我使用贝尔算法进行排列解决了它,但我无法理解递归方法。我在网上搜索并找到了这段代码:

void permute(char *a, int i, int n) 
{
   int j; 
   if (i == n)
     printf("%s\n", a);
   else
   {
        for (j = i; j <= n; j++)
       {
          swap((a+i), (a+j));
          permute(a, i+1, n);
          swap((a+i), (a+j)); 
       }
   }
} 

我无法理解这个算法基本上是如何工作的?我什至尝试过干跑!

如何应用回溯?

它是否比贝尔算法更有效地计算置换?

4

8 回答 8

24

该算法基本上适用于这个逻辑:

字符串 X 的所有排列与 X 中每个可能字符的所有排列相同,再加上字符串 X 中没有该字母的所有排列。

也就是说,“abcd”的所有排列都是

  • "a" 与 "bcd" 的所有排列相连接
  • "b" 与 "acd" 的所有排列相连接
  • "c" 与 "bad" 的所有排列相连接
  • “d”与“bca”的所有排列相连接

该算法尤其不是对子字符串执行递归,而是在输入字符串上执行递归,不占用额外的内存来分配子字符串。“回溯”撤消对字符串的更改,使其保持原始状态。

于 2013-06-07T17:28:03.853 回答
14

代码有 2 个问题,都与n假定的字符串长度有关。代码for (j = i; j <= n; j++) { swap((a+i), (a+j)); ...交换字符串的空字符'\0'并给出代码截断结果。检查(i == n)应该是原件(i == (n-1))

通过调用swap()两次有效撤消其原始交换来应用回溯。

贝尔算法的复杂度顺序相同。

#include <stdio.h>

void swap(char *a, char *b) { char t = *a; *a = *b; *b = t; }

void permute(char *a, int i, int n) {
   // If we are at the last letter, print it
   if (i == (n-1)) printf("%s\n", a);
   else {
     // Show all the permutations with the first i-1 letters fixed and 
     // swapping the i'th letter for each of the remaining ones.
     for (int j = i; j < n; j++) {
       swap((a+i), (a+j));
       permute(a, i+1, n);
       swap((a+i), (a+j));
     }
  }
}

char s[100];
strcpy(s, "ABCD");
permute(s, 0, strlen(s));
于 2013-06-12T01:14:02.227 回答
10

您找到的代码是正确的!该算法将字符串中的当前字符与所有后续字符交换并递归调用该函数。它很难用语言来解释。下图可能对你有所帮助。

Backracking 在第二次交换中进行,以反转第一次交换的效果,即我们将返回原始字符串,现在将数组中的下一个字符与当前字符交换。算法的时间复杂度。是 O(n*n!) 因为循环运行 n 次并且置换函数被称为 n! 次。(对于第 1 次迭代,它被称为 n 次;对于第 2 次迭代 (n-1) 次,依此类推)。

用于字符串排列的递归树

资料来源http ://www.geeksforgeeks.org/write-ac-program-to-print-all-permutations-of-a-given-string/

于 2013-11-03T07:56:06.250 回答
5

Recursion really simplifies it:

public static void permutation(String str) 
{ 
    permutation("", str); 
}

private static void permutation(String prefix, String str) 
{
    int n = str.length();
    if (n == 0) {
        System.out.println(prefix);
    } else {
        for (int i = 0; i < n; i++)
            permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i+1, n));
    }
}
于 2014-02-18T10:21:46.937 回答
1
I create more specific but not efficient Program for permutation for general string.
It's work nice way.
//ubuntu 13.10 and g++ compiler but it's works on any platform and OS
//All Permutation of general string.

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
using namespace std;
int len;
string str;

void permutation(int cnum)
{
    int mid;
    int flag=1;
    int giga=0;
    int dead=0;
    int array[50];
    for(int i=0;i<len-1;i++)
    {
        array[50]='\0';
        dead=0;
        for(int j=cnum;j<len+cnum;j++)
        {
            mid=j%len;
            if(mid==cnum && flag==1)
            {
                cout<<str[mid];
                array[dead]=mid;
                dead++;
                flag=0;
            }
                else
            {
                giga=(i+j)%len;
                for(int k=0;k<dead;k++)                 
                {
                    if((array[k]==giga) && flag==0)
                    {
                    giga=(giga+1)%len;
                    }
                }
                cout<<str[giga];
                array[dead]=giga;
                dead++;

            }
        }
        cout<<endl;
        flag=1; 
    }
}
int main()
{
    cout<<"Enter the string :: ";
    getline(cin,str);
    len=str.length();
    cout<<"String length = "<<len<<endl;
    cout<<"Total permutation = "<<len*(len-1)<<endl;
    for(int j=0;j<len;j++)
    {
        permutation(j);
    }
return 0;
}
于 2014-10-09T19:21:22.633 回答
1

伪代码:

String permute(String a[])
{
  if (a[].length == 1)
     return a[];
  for (i = 0, i < a[].length(); i++)
    append(a[i], permute(a[].remove(i)));
}
于 2014-05-22T03:07:20.530 回答
0
# include <stdio.h>

/* Function to swap values at two pointers */
void swap (char *x, char *y)
{
     char temp;
     temp = *x;
     *x = *y;
     *y = temp;
}

/* Function to print permutations of string
    This function takes three parameters:
    1. String
    2. Starting index of the string
    3. Ending index of the string. */
void permute(char *a, int i, int n)
{
    int j;
    if (i == n)
      printf("%s\n", a);
    else
    {
          for (j = i; j <= n; j++)
         {
             swap((a+i), (a+j));
             permute(a, i+1, n);
             swap((a+i), (a+j)); //backtrack
         }
    }
}

/* Driver program to test above functions */
int main()
{
    char a[] = "ABC";
    permute(a, 0, 2);
    getchar();
    return 0;
}
于 2014-03-15T23:13:23.990 回答
0
def perms(s):
    if len(s) < 1:
        return [s]
    ps = []
    for i in range(0, len(s)):
        head, tail = s[i], s[0:i] + s[i + 1:]
        ps.extend([head + tailp for tailp in perms(tail)])
    return ps
于 2016-11-13T22:40:36.523 回答