題目:輸入乙個字串,列印出該字串中字元的所有排列。例如:輸入字元abc,則列印所有組合字串:abc,acb,bac,bca,cab,cba
分析:把複雜的問題進行分解,變成更小的問題。分治法一般很容易想到用遞迴。
首先理解遞迴:參見
遞迴演算法有四個特性:
必須有可達到的終止條件,否則程式陷入死迴圈 (結合本題,本題終止條件是?這一點很重要)
子問題在規模上比原問題小
子問題可通過再次遞迴呼叫求解
子問題的解應能組合成整個問題的解
通過找規律,求字串的全排列,可以看出三步:
首先,求所有可能出現在第乙個位置的字元,其次,把第乙個字元和其後面的字元一一交換。如下圖所示,分別把第乙個字元a和後面的b、c等字元交換的情形。
接著,固定第乙個字元,求後面所有字元的排列。這個時候我們仍把後面的所有字元分成兩部分:後面字元的第乙個字元,以及這個字元之後的所有字元。然後把第乙個字元逐一和它後面的字元交換
下面的遞迴的圖示意圖:
**結合上面的示意圖看就非常清晰了:
#includeusing擴充套件1---去重當字串有字元是重複,那麼顯然我們會列印出重複的字元,怎麼解決呢?namespace
std;
#include
void permutation(char *pstr,char *pbegin)}}
全排列中去掉重複的規則——去重的全排列就是從第乙個數字起每個數分別與它後面非重複出現的數字交換。
增加**:
#includeusing擴充套件2---八皇后問題namespace
std;
#include
//在[nbegin,nend)區間中是否有字元與下標為pend的字元相等
bool isswap(char* pbegin , char*pend)
return
true;}
void permutation(char* pstr , char *pbegin)
else}}
}int main(void
)
分析:為了簡化問題,我們這麼分析,由於8皇后的任意兩個不能處於同一行,那麼也就是每一行對應乙個皇后,找我們可以定義乙個陣列:columnindex[8]=,其中第i個元素對應的是第i行所對應的列。這樣一來,由於裡面的8個數字是不相同的,所以對應的列也不相同,那麼剩下的就是要排除不在同一對角線上的皇后了,也就是:i-j=columnindex[i]-columnindex[j]和j-i=columnindex[i]-columnindex[j]
這其實就是乙個全排列問題,排除違反條件下所有的情況。
結論:如果面試題是按照一定要求擺放若干個數字,我們可以先求出這些數字的所有排列,然後再一一判斷每個排列是不是滿足題目要求。
**與擴充套件一---去重類似:如下:
#includeusing參考:namespace
std;
int g_number = 0
;void permutation(int * , int , int
);void print(int * , int
);void
eightqueen( )
bool check(int columnindex , int
length)
}return
true;}
void permutation(int columnindex , int length , int
index)
}else
}}void print(int columnindex , int
length)
int main(void
)
字串的排列 全排列
輸入乙個字串,按字典序列印出該字串中字元的所有排列。例如輸入字串abc,則列印出由字元a,b,c所能排列出來的所有字串abc,acb,bac,bca,cab和cba。輸入乙個字串,長度不超過9 可能有字元重複 字元只包括大小寫字母。使用itertools中的permutations,可以實現全排列 ...
遞迴 字串全排列 全排列
在高中階段我們已經通過大量的習題了解了排列和組合。但是有時候我們研究的不是由排列和組合算出來的數字,研究的是生成排列和組合。即,把集合中元素所有的排列和組合全部列出來,然後研究這些序列的性質。今天我用兩種方法講一下如何生成排列。注意我們這裡涉及的順序都是序列的字典序。序列的字典序 設有兩個序列,第乙...
字串全排列
依次選出每乙個字元元素,作為排列的第乙個元素,然後對剩餘的元素進行全排列,如此遞迴處理,從而得到所有元素的全排列。以對字串abc進行全排列為例,我們可以這麼做 固定a,求後面bc的排列 abc,acb,求好後,a和b交換,得到bac 固定b,求後面ac的排列 bac,bca,求好後,c放到第一位置,...