排列問題
問題描述:已知字符串的中字符是互不相同的,求所有可能的字符排列。例如輸入序列ab,則得到的所有可能序列應當為aa、ab、ba、bb
思路:此題目可以采用遞歸的思想,由于所有可能排列的位數均是n位,可以利用一個長度為n的數組array[]來存放最終要輸出的結果,并以array_pos表示數組中存放的字符下標,當array_pos==len時,輸出array的值。由于含有n個字符的字符串,滿足條件的排列共有n^n個,因此在遞歸當中需要用到一個for循環。
設f(str,array,len,pos)為輸出可能的排列序列的函數,則遞歸模型如下:
終止條件:f(str,array,len,pos) ≡ {輸出符合條件的排列;return} 若len==array_pos
遞歸主體:f(str,array,len,pos) ≡ {將str中對應的字符暫存到array中;
f(str,array,len,pos+1)} 若len ≠ array_pos
#include <iostream>
using namespace std;
void Permutation(const char *str,char array[],int len, int array_pos) {
if (len == array_pos) {
for (int i = 0; i < len; i++)
cout << array[i];
cout << endl;
return;
}
for (int j = 0; j < len; j++) {
array[array_pos] = str[j];
Permutation(str, array, len, array_pos+1);
}
}
int main()
{
const char* str = "abc";
char* array = new char[3];
int length = strlen(str);
Permutation(str, array, length, 0);
return 0;
}
時間復雜度:O(n^n),空間復雜度:O(n)
組合問題
問題描述:已知字符串中的字符是互不相同的,編寫程序輸出字符串的任意組合,例如給定abc,則任意組合為a、b、c、ab、ac、bc、abc
解法一:此題目可以采用遞歸的方式進行處理,對于n個字符中,取m個字符的排列,可分為如下兩種情況
情況①:將第1個元素保留,并在剩余的n-1個元素中選取m-1個元素進行組合
情況②:跳過第1個元素,在剩余的n-1個元素中選取m個元素進行組合
設f(str,buf,num)為輸出任意組合的函數,則遞歸模型如下:
終止條件:f(str,buf,num) ≡ {輸出buf;return}
若num==0【在n個元素中,能夠找到符合條件的m個字符組成的組合】
f(str,buf,num) ≡ {不做任何事情,直接return}
若*str=='\0'【在n個元素中,找不到符合條件的m個字符組成的組合】
遞歸主體:f(str,buf,num) ≡ {將str中的字符暫存至buf中;
f(str+1,buf,num-1)} 對應情形1
f(str,buf,num) ≡ {將buf中的字符刪除;
f(str+1,buf,num)} 對應情形2
#include <iostream>
#include <vector>
using namespace std;
void output(vector<char> buffer) {
for (vector<char>::iterator iter = buffer.begin(); iter != buffer.end(); iter++)
cout << *iter;
cout << endl;
}
void Combination(const char* str,vector<char> &buffer,int num) {
if (num == 0) {
output(buffer);
return;
}
if (*str == '\0')
return;
buffer.push_back(*str);
Combination(str + 1, buffer, num - 1);
buffer.pop_back();
Combination(str + 1, buffer, num);
}
int main(){
vector<char> buffer;
char str[] = "abc";
int length = sizeof(str) / sizeof(char);
for (int i = 1; i < length; i++)
Combination(str, buffer, i);
return 0;
}
解法二:利用位運算
對于n個字符的字符串,其可能的組合有2^n-1種,以abc為例,則利用二進制進行表示,用1表示字符輸出,0表示字符不被輸出,則所有可能的結果均可表示為a(100)、b(010)、c(001)、ab(110)、ac(101)、bc(011)、abc(111)
#include <iostream>
using namespace std;
void Combination(const char* str,int len) {
for (int i = 1; i < (1 << len); i++) { //1<<len相當于得到2^n,實現從1~2^n-1的遍歷
for (int j = 0; j < len; j++)
if (i & (1 << j)) //將對應為為1的字符輸出
cout << str[j];
cout << endl;
}
}
int main()
{
const char str[] = "abcd";
int len = strlen(str);
Combination(str,len);
return 0;
}
參考資料:《編程之法—面試和算法心得》習題