28. 字符串的排列之第1篇[StringPermutation]

【题目】

输入一个字符串,打印出该字符串中字符的所有排列。例如输入字符串abc,则输出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。

分析】

这是一道很好的考查对递归理解的编程题,因此在过去一年中频繁出现在各大公司的面试、笔试题中。

我们以三个字符abc为例来分析一下求字符串排列的过程。首先我们固定第一个字符a,求后面两个字符bc的排列。当两个字符bc的排列求好之后,我们把第一个字符a和后面的b交换,得到bac,接着我们固定第一个字符b,求后面两个字符ac的排列。现在是把c放到第一位置的时候了。记住前面我们已经把原先的第一个字符a和后面的b做了交换,为了保证这次c仍然是和原先处在第一位置的a交换,我们在拿c和第一个字符交换之前,先要把b和a交换回来。在交换b和a之后,再拿c和处在第一位置的a进行交换,得到cba。我们再次固定第一个字符c,求后面两个字符b、a的排列。

既然我们已经知道怎么求三个字符的排列,那么固定第一个字符之后求后面两个字符的排列,就是典型的递归思路了。

【代码】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 

// case 1: abc
void R(char *str, int len, int index)
{
    
//base case
    if (index == len)
    {
        Print(str);
        
return;
    }

    
for (int i = index; i < len; i++)
    {
        swap(str[index], str[i]);
        R(str, len, index + 
1);
        swap(str[index], str[i]);
    }
}

// abc ---> abc acb bac bca cab cba
void Permutation(char *str)
{
    
if (str == NULL)
        
return;
    
int len = strlen(str);
    R(str, len, 
0);
}


void r_permutation(char *str, char *index)
{
    
if (*index == '\0')
    {
        printf(
"%s\n", str);
        
return;
    }
    
for (char *ch = index; *ch != '\0'; ch++)
    {
        swap(*ch, *index);
        r_permutation(str, index + 
1);
        swap(*ch, *index);
    }
}

void premutation(char *str)
{
    
if (str == NULL)
        
return;
    r_permutation(str, str);
}

【扩展1】

如果不是求字符的所有排列,而是求字符的所有组合,应该怎么办呢?当输入的字符串中含有相同的字符时,应该如何处理?举个例子,如果输入abc,它的组合有a、b、c、ab、ac、bc、abc。

【扩展2】

输入一个含有8个数字的数组,判断有没有可能把这8个数字分别放到正方体的8个顶点上,使得正方体上三组相对的面上的4个顶点的和相等。

提示:全排列,然后满足特定条件。

【参考】

 http://zhedahht.blog.163.com/blog/static/254111742007499363479/