转载请说明出处:http://blog.youkuaiyun.com/shanzhd/article/details/7597375
问题如下:
输入一个字符串,例如“abc”,它可能的排列方式有:abc, acb, bac, bca, cab, cba,一共有六种排列方式。
那么,输入任意字符串,它可能的排列方式有多少种?
分析,假设字符总数为N
1)如果没有重复的字符,那么排列总数是N!(N的阶乘)。
2)如果有一个字符重复了M次,那么排列总数是 N! / M!。
3)如果有两个字符分别重复了 P和Q次,那么排列总数是 (N! / P!) / Q!。
4)如2)和3)的规律依次类推。
上述算法的C++实现如下:
// test.cpp
#include <iostream>
using namespace std;
#include <vector>
#include <string>
typedef pair<char, int> char_count;
long long getPermutationsNumFromLength(int n)
{
long long total = n;
while (--n > 1) {
total *= n;
}
return total;
}
long long getPermutationsNumFromString(const string &str)
{
long long count = 0;
int len = str.length();
if (len <= 1) {
return len;
} else if (len > 20) {
return -1; //overflow.
}
//Statistics about the numbers of duplicate.
vector<char_count> statistics;
bool found = false;
for (string::const_iterator istr = str.begin(); istr != str.end(); ++istr) {
found = false;
for (vector<char_count>::iterator ista = statistics.begin(); ista != statistics.end(); ++ista) {
if (*istr == ista->first) {
ista->second++;
found = true;
break;
}
}
if (!found) {
statistics.push_back(char_count(*istr, 1));
}
}
//Get the total number.
count = getPermutationsNumFromLength(len);
//Remove the duplicate number.
for (vector<char_count>::iterator ista = statistics.begin(); ista != statistics.end(); ++ista) {
if (ista->second > 1) {
count /= getPermutationsNumFromLength(ista->second);
}
}
return count;
}
int main()
{
string str;
long long num;
while (1) {
cout << "Please enter the string('q' to exit): ";
cin >> str;
if (str == "q") {
break;
}
num = getPermutationsNumFromString(str);
if (-1 == num) {
cout << "String length overflow (should be less than 21)." << endl;
continue;
}
cout << "The number of permutations is " << num << endl;
}
return 0;
}