输出N个字母的全排列问题

1.全排列的重点在于各字母出现的频数而不是对字符串的调整。以回溯的方式,通过操作字母表的频数和当前string的位数来实现全排列。

2.可以采用递归法或STL。

3.STL中已经有轮子--bool next_permutation(itr1,itr2),此算法需要配合sort()使用。

以下是原文:                                                                                           <转自:http://www.cnblogs.com/lanxuezaipiao/p/3299601.html>

问题描述:求全由小写字母组成的不超过200个字符序列的全排列
如输入序列bbjd,排列结果为:
bbdj
bbjd
bdbj
bdjb
bjbd
bjdb
dbbj
dbjb
djbb
jbbd
jbdb
jdbb
 
方法一:递归法
 
代码如下:
#include <stdio.h>

int t[200];
char s[200];
int n = 0;

void permutation(int i)
{
    int k;

    // a~z的ASCII码在97到122之间
    for(k = 97; k < 123; k++)
    {
        if(t[k])
        {
            t[s[i] = k]--;
            permutation(i + 1);
            t[k]++;
        }
    }

    // 只有n个字母全部排好了才输出
    n - i || puts(s);
}

int main()
{    
    int i;

    puts("Please Input letter sequence: ");
    gets(s);

    // t[]记录每个字母的出现频率
    // n为待排序列的长度
    for(i = 0; s[i] != '\0'; i++)
    {
        t[s[i]]++;
        n++;
    }

    puts("Permutation result: ");
    permutation(0);

    return 0;
}

方法二:STL法

C++的STL有一个函数可以方便地生成全排列,这就是next_permutation

在C++ Reference中查看了一下next_permutation的函数声明:

#include <algorithm>
bool next_permutation( iterator start, iterator end );

The next_permutation() function attempts to transform the given range of elements [start,end) into the next lexicographically greater permutation of elements. If it succeeds, it returns true, otherwise, it returns false.

 

从说明中可以看到 next_permutation 的返回值是布尔类型。按照提示写了一个标准C++程序:

其中用到了 sort 函数,如果不先排序,则完成不了全排列。

 

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

int main()
{
    string str;

    cout << "Please Input letter sequence: \n";
    cin >> str;
    
    // 必须先排序
    sort(str.begin(), str.end());
    cout << str << endl;

    cout << "Permutation result: \n";

    while(next_permutation(str.begin(), str.end()))
    {
        cout << str << endl;
    }

    return 0;
}

在使用稍大数据测试的时候,发现标准C++的效率很差,换成C函数写一下,效率提升了许多倍,比如我用字符序列“aabbddef”作为测试,上面C++代码用了6s,而下面的C代码只用了0.918s。所以,平时写代码时能用C就用C。
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用C语言输出前N个字母的有重复全排列的代码: ``` #include <stdio.h> #include <string.h> #define MAX_N 26 // 最多支持26个字母 int n; // 字母个数 char letters[MAX_N]; // 存储字母 int count[MAX_N]; // 存储每个字母的数量 char output[MAX_N]; // 存储当前输出的排列 // 输出全排列 void permute(int index) { if (index == n) { // 已经输出了n个字母 printf("%s\n", output); return; } for (int i = 0; i < n; i++) { if (count[i] > 0) { // 还有剩余的该字母 output[index] = letters[i]; // 将该字母加入当前输出的排列 count[i]--; // 该字母剩余数量减1 permute(index + 1); // 递归输出下一个字母 count[i]++; // 恢复该字母剩余数量 } } } int main() { printf("请输入字母个数n:"); scanf("%d", &n); printf("请输入%d个字母(用空格隔开):", n); for (int i = 0; i < n; i++) { scanf(" %c", &letters[i]); } memset(count, 0, sizeof(count)); // 初始化count数组 for (int i = 0; i < n; i++) { count[letters[i] - 'a']++; // 统计每个字母的数量 } memset(output, 0, sizeof(output)); // 初始化output数组 permute(0); // 输出全排列 return 0; } ``` 该程序先读入字母个数和字母数组,然后统计每个字母的数量。接着从第一个字母开始,依次枚举每个字母,如果该字母还有剩余数量,则将其加入当前输出的排列中,并递归输出下一个字母。当输出字母个数达到n个时,即可输出一种排列。重复执行该过程,直到输出所有的排列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值