全排列问题--去重


字符串的全排列去重问题

在上一篇全排列问题-点我查看中,对题目稍加修改:
给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 我们假设对于小写字母有'a' < 'b' < ... < 'y' < 'z',而且给定的字符串中的字母已经按照从小到大的顺序排列。

即不再给定不同的小写字符,而是可能存在相同的字母,那么按照我们上篇文章的算法就可能产生很多重复性的结果,如输入aab后,会有如下结果:

[root@localhost ACM]# ./a.out 
aab
aab
aab
aba
aba
baa
baa

这里就涉及到去重问题了,最简单的做法是输出结果时进行过滤即可:

        string tmpStr;
        for(int i = 0;i < count;i++)
        {
            if(tmpStr == allprem[i])
                continue;
            cout << allprem[i] << endl;
            tmpStr = allprem[i];
        }

当然,如果是在计算过程中去掉重复的也是OK的,主要原理是:当第i个字符需要固定到首个字符时,要先检查下之前有没有固定过该字符,如果有则没有必要交换了,继续下个计算即可,代码如下:

#include 
#include 
#include 
#include 
using namespace std;

char allprem[1000][7];
int count = 0;

bool isSwap(const char* str,int start,int end)
{
    for(int k = start;k < end;k++)
    {
        if(str[end] == str[k])
        {
            return false;
        }
    }
    return true;
}

void swap(char* str,int a,int b)
{
    char tmp = str[b];
    str[b] = str[a];
    str[a] = tmp;
}
void perm(char* str,int start,int end)
{
    if(start == end - 1)
    {
        strcpy(allprem[count],str);
        count++;
    }
    else
    {
        for(int k = start;k < end;k++)
        {
            if(isSwap(str,start,k))
            {
                swap(str,k,start);
                perm(str,start+1,end);
                swap(str,k,start);
            }
        }
    }
}

int compare(const void * a,const void* b)
{
    return strcmp((char*)a,(char*)b);
}
int main()
{
    char inputStrr[7] = {0};
    while(cin >> inputStrr)
    {   
        count = 0;
        perm(inputStrr,0,strlen(inputStrr));
        
        qsort(allprem,count,sizeof(allprem[0]),compare);
        
        for(int i = 0;i < count;i++)
        {
            cout << allprem[i] << endl;
        }
    }
    return 0;
}


程序测试:

[root@localhost ACM]# ./a.out              
abb
abb
bab
bba

你可能感兴趣的:(全排列问题--去重)