什么是制作字符串的所有可能组合的最佳算法?

时间:2012-07-13 14:30:34

标签: string algorithm permutation

我发现其他类似的问题太复杂了。

我认为这意味着如果我们获得底池,那么组合将是 锅 选择 最佳 锅 PTO 锅

所以我写了下面的代码:

#include<iostream>
#include<string.h>
using namespace std;

int main(){

    char s[10];
    char temp;
    cin>>s;
    char t[10];
    for(int i=0;i<3;i++)
    {
        for(int j=i;j<3;j++)
        {

            strcpy(t,s);
            temp=s[i];
            s[i]=s[j];
            s[j]=temp;

            cout<<s<<"\n";
            strcpy(s,t);
        }
    }

有更好的方法吗?

2 个答案:

答案 0 :(得分:4)

这个问题本质上是O(N!)(阶乘)复杂性问题。原因在于,对于每个潜在单词的每个位置,可以填充该位置的字符的可能性递减,例如,有4个字母a,b,c和d。

           -----------------
Positions: | 0 | 1 | 2 | 3 |
           -----------------

In position 0, there are 4 possibilities, a, b, c, or d

Lets fill with a

        -----------------
String: | a |   |   |   |
        -----------------

Now Position 1 has 3 possibilities of fill letters b, c, or d

Lets fill with b

        -----------------
String: | a | b |   |   |
        -----------------

Now Position 2 has 2 possibilities of fill letters c, or d

Lets fill with c

        -----------------
String: | a | b | c |   |
        -----------------

Now Position 1 has only 1 possibility for a fill letter: d

        -----------------
String: | a | b | c | d |
        -----------------

这仅适用于1个字符串,复杂性来自(在这种情况下)可以填充给定输出字的字符位置的潜在可能性,因此:

4 * 3 * 2 * 1 = 4!

这可以扩展到任意数量的输入字母,正好是N!如果没有重复的字母。这也代表了你应该得到的数量。

执行此类操作的代码可以是(在C中测试和工作):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define TRUE  1
#define FALSE 0

void printPermutations(int level, const char * inString, char * outString){

    unsigned int len = strlen(inString);
    char * unusedLetter;
    int j;

    if( 1 == len ){
        printf("%s%s\n", outString, inString);
    }else{
        unusedLetters = (char *)malloc(sizeof(char) * (len - 1));

        for(int startLetter = 0; startLetter < len; startLetter++){

            outString[level] = inString[startLetter];

            // setup the "rest of string" string
            j = 0;
            for(int i = 0; i < len; i++){ 
                if( i != startLetter ){        
                    unusedLetter[j] = inString[i];
                    j++;
                }
            }

            // recursive call to THIS routine
            printPermutations(level+1, unusedLetters, outString);
        }
    }
}

int main(int argc, char * argv[]){
    unsigned int len;
    char * outString;

    if(argc != 2) return 0;

    len = strlen(argv[1]);
    outString      = (char *)malloc(sizeof(char) * (len + 1));
    outstring[len] = '\0';

    printPermutations(0, argv[1], outString);

    return 0;
}

从外面打电话,如下:

projectName abc

使用“abc”

输出样本
abc
acb
bac
bca
cab
cba

如果有重复的字母,请说a,a,b,c

那么总会有重复的话。

对于这些情况,UNIQUE结果词的数量应该是因子的唯一字符数量,因此对于上述情况,它将是3!不是4!。

这样做的原因是a填充给定点并不重要,因此给出的唯一性是提供的唯一字母数量。这也是一个难题,我会说你应该生成所有N!首先是单词,然后运行第二个算法来搜索重复单词并删除。可能有更聪明的方法可以动态生成独特的单词。

答案 1 :(得分:3)

以下解决方案是O(N!)。这也需要重复考虑:

    #include<stdio.h>
    void permute(char s[10],char *p);
    int count=0;

    main(){
        char s[10];
        int i;
        scanf("%s",s);
        permute(s,s);
        }

    //takes into account repetetion
    void permute(char s[10],char *p){
        char *swap,temp;
        if(*(p+1)==0) {
            count++;
            printf("%4d] %s\n",count,s);
        }
        else{
            for(swap=p;*swap;++swap){
                char *same;
                for(same=p;*same!=*swap;++same){};
                if(same==swap){
                temp=*swap;
                *swap=*p;
                *p=temp;
                permute(s,p+1);
                *p=*swap;/*restoring the original string*/
                *swap=temp;
                }
            }
        }
    }