【问题标题】:Print all the permutations of a string in C在 C 中打印字符串的所有排列
【发布时间】:2013-06-07 17:22:01
【问题描述】:

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

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)); 
       }
   }
} 

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

如何应用回溯?

在计算置换方面,它是否比贝尔算法更有效?

【问题讨论】:

  • 为什么不添加一些有用的 printfs,然后尝试运行它?

标签: c string algorithm permutation


【解决方案1】:

算法基本上是按照这个逻辑工作的:

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

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

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

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

【讨论】:

    【解决方案2】:

    代码有 2 个问题,都与假定的字符串长度 n 有关。代码for (j = i; j &lt;= 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));
    

    【讨论】:

    • 您能否在 OP 的算法失败并且您的算法给出正确结果的情况下进行一些测试。我通过传递字符串的开始和结束索引来调用 OP 的算法,它每次都给出正确的结果。
    • @Deepankar Singh 1) 澄清“字符串的结束索引”,是s[ending_ index] == '\0' 还是s[ending_ index+1] == '\0'?您的测试是否包括奇数/偶数长度字符串和 0 长度字符串?
    • @Deepankar Singh OP 帖子的关键问题是没有明确发布如何确定n 是如何为初始呼叫确定的——这可能是所研究网站上文档不足的结果。使用int n = strlen("abc"); permute("abc",0,n) 看起来是合理的。 "abc"[3] 是空字符,是字符串的最后一个字符,所以可以认为是“字符串的结束索引”。然而,我认为要使 OP 代码正常工作,需要int n = strlen("abc") - 1;。不幸的是,permute("",0,strlen("")-1)n 存在利基问题,因为 strlen(s)-1 是违反直觉的。
    • 我同意OP没有指定n的初始值,但是看到他的for循环条件 "j
    • @Deepankar Singh 很多时候,.h 文件中的函数声明是主要文档。考虑一个孤独的void permute(char *a, int i, int n),人们会期待什么?使用 OP:“我无法理解递归方法” - 存在一些问题。我首先认为n 是数组大小,然后是字符串长度,但不是-它是字符串长度减1。代码可能是void permute(char *a, int i, int length_minus_1)
    【解决方案3】:

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

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

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

    【讨论】:

    【解决方案4】:

    递归确实简化了它:

    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));
        }
    }
    

    【讨论】:

    • 有多余的花括号去掉。
    • 同意@Ashish,这是一个很好的C++解决方案。这篇文章被标记为 C,上面的代码显然没有转换。也许发布一个 C 解决方案?
    • @chux 这不是 C++,我认为是 Java
    【解决方案5】:

    伪代码:

    String permute(String a[])
    {
      if (a[].length == 1)
         return a[];
      for (i = 0, i < a[].length(); i++)
        append(a[i], permute(a[].remove(i)));
    }
    

    【讨论】:

      【解决方案6】:
      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;
      }
      

      【讨论】:

        【解决方案7】:
        # 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;
        }
        

        【讨论】:

          【解决方案8】:
          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
          

          【讨论】:

            猜你喜欢
            • 2017-02-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-03-20
            • 2018-03-07
            • 1970-01-01
            相关资源
            最近更新 更多