遞迴解決全排列問題+詳細圖解遞迴執行
阿新 • • 發佈:2019-01-22
問題描述:字串的排列
//輸入一個字串, 按字典序打印出該字串中字元的所有排列。
//例如輸入字串abc, 則打印出由字元a, b, c所能排列出來的所有字串abc, acb, bac, bca, cab和cba。
//結果請按字母順序輸出。
//長度不超過9(可能有字元重複), 字元只包括大小寫字母。
分析:
採用分治法,把一個字串看成兩部分:第一部分是它的第一個字元,第二部分是後面的所有字元。
(1)首先求所有可能出現在第一個位置的字元,也就是把第一個字元和後面的所有字元交換;
(2)把後面的字串看成一個新的字串,重複上面步驟。
程式碼:
void PermutationLocal(string str, vector<string>& ret, int index) { if (index == str.length()-1) //一次遞迴結束條件 { ret.push_back(str); } else { for (size_t i = index; i < str.length(); ++i) { if(i != index && str[i] == str[index]) { continue; } //std:swap(str[i], str[index]); //交換 char tmp = str[i]; str[i] = str[index]; str[index] = tmp; PermutationLocal(str, ret, index + 1); } } } vector<string> Permutation(string str) { vector<string> ret; int index = 0; if (!str.empty()) { PermutationLocal(str, ret, index); } return ret; }
測試:
void main()
{
vector<string> v;
v = Permutation("abc");
for(auto i : v)
cout << i.c_str() << endl;
}
遞迴詳解(除錯圖解):
(1)遞迴初始化:
(2)第一次PermutationLocal:
(3)第二次PermutationLocal:
如上圖,index = 2,本次遞迴將要結束,
ret插入了值。
(4)隨後本次遞迴被丟擲棧,直接跳轉到上次遞迴的“”斷點“”,開始繼續執行。其實我覺得理解遞迴,重點、關鍵是要理解“函式棧”、“儲存函式斷點”、“返回函式斷點”!
後面步驟不再截圖贅述,請自行除錯、觀察資料變化、堆疊變化、執行流程。