排列 組合
排列
字符串的全排列這種是給你一個序列,讓你找出他的全排列,每個位置不重複。(交換)
例如 abc的全排列有 abc, acb, bac, bca, cab, cba
還有一種是每個位置可以重複。(所有可能)
例如 abc的全排列 aaa, aab, aac, aba, abb,abc,....
類似於 輸出求n位的每個數 0 ~ 9999....9(n位), 前面的例題。
!!!!對於這種問題,我們把 字符串看成2部分
第一部分 是字符串的第一個字符
第二部分 是字符串的後面的所有字符。
對於交換,先求出第一部分所有可能,再將第一部分的字符和第二部分的所有字符交換。
關於所有可能,先求出第一部分所有可能,和第二部分所有可能。
對於第二部分再遞歸調用。再看成2部分。
遞歸函數
/// index 用來監測是否遞歸到最後了,到最後則輸出。
paiLie(char * a, char *index)
{
if('\0' == *index )
cout<< a <<endl; ///到達末尾,可以輸出了
else
{
/// (1)交換的話
char tmp, *p;
for(p = index; *p != '\0'; ++p)
{
tmp = *p;
*p = *index;
*index = tmp;
paiLie(a, index + 1);
tmp = *p;
*p = *index;
*index = tmp;
}
///(2)所有可能
int i;
for(i = 0; i < 10; ++i)
{
*p = '0' + i;
paiLie(a, index+1);
}
///(3) 上面是每一位都是0~9的數字,還可以指定每一位的取值範圍
/// 這樣函數的參數就有需要添加一個base[]
/// paiLie(char * a, char *index, char * base, int baseNum)
int i;
for(i = 0; i < baseNum; ++i)
{
*p = base[i];
paiLie(a, index + 1, base);
}
}
}
/// index 用來監測是否遞歸到最後了,到最後則輸出。
調用該遞歸函數的話。
main()
{
char a[N+1];
a[N] = '\0';
paiLie(a, a);
}
組合
(2)字符的所有組合例如 abc 的所有組合--- a ,b, c, ab, ac, bc, abc = (2 ^3 -1) 種
對於每一種組合來說,組合數爲m , 1<= m <= n;
(1)包括第一個字符, + 不包括第一個字符的m-1個字符的組合
(2)不包括第一個字符 + 不包括第一個字符的m個字符的組合
<span style="font-size:18px;">allZuhe(char * base)
{
int length = strlen(base);
char *result = new char[length + 1];
for(i = 1; i <= length; ++i)
{
allZuhe_recurse(base, 0, result, 0, i);
}
delete[] result;
}
allZuhe_recurse(char *base, int baseIndex,
char *result, int resultIndex, int zuheNum)
{
if(0 == zuheNum)
{
result[resultIndex] = '\0';
cout<<result<<endl;
}
else
{
if('\0' != base[baseIndex])
{
/// 包括第一個字符 + 不包括第一個字符的m-1個字符的組合。
result[resultIndex] = base[baseIndex];
allZuhe_recurse(base, baseIndex+1, result, resultIndex+1, zuheNum-1);
/// 不包括第一個字符 + 不包括第一個字符的m個字符的組合。
allZuhe_recurse(base, baseIndex, result, resultIndex, zuheNum);
}
}
}</span>