輸入一個字符串,打印出該字符串中字符的所有排列。
例如輸入字符串abc,則打印出由字符a、b、c所能排列出來的所有字符串abc, acb , bac、bca, cab cba。
由於字符串的長度不同, 使用for循環嵌套枚舉是不行的, 需要使用遞歸才能處理不定長度的字符串.
需要把字符全排列, 每個字符都可能出現在第一位置, 可以看成 完整字符 = 單個字符 + 剩餘字符的全排列 , 剩餘字符的全排列 = 單個字符 + (剩餘字符-單個字符)的全排列, 這樣下去,剩餘字符會越來越少, 當剩餘字符沒有時, 說明全排列已經完成了.
現在說一個例子 ,
ABCD的全排列 = A + BCD的全排列; ABCD的全排列 = B + ACD的全排列; ABCD的全排列 = C + ABD的全排列; ABCD的全排列 = D + ABC的全排列;
BCD的全排列 = B + CD的全排列; BCD的全排列 = C + BD的全排列; BCD的全排列 = D + BC的全排列;
CD的全排列 = C + D; CD的全排列 = D + C ;
經過這樣分解子問題 , 就可以寫出遞歸的代碼了.
- (void)viewDidLoad {
[super viewDidLoad];
[self logAllString];
}
// 枚舉字符串的所有組合
- (void)logAllString {
NSString * str = @"ABCD";
// 把str的每個字符加入到數組中
NSMutableArray<NSString *> * array = [NSMutableArray arrayWithCapacity:str.length];
for (int i = 0; i<str.length; i++) {
[array addObject:[str substringWithRange:NSMakeRange(i, 1)]];
}
[self __logString:@"" withLeftArray:array];
}
/// 每次都是 原始字符串+剩下的沒有處理的數組
- (void)__logString:(NSString *)str withLeftArray:(NSMutableArray *)leftArray{
if (leftArray.count==0) {
static int count = 1;
NSLog(@"%@ 第%d種",str,count++);
return;
}
for (NSString * oneChar in leftArray) {
// 從剩餘的數組中移除本次添加的oneChar
NSMutableArray * copyArray = [leftArray mutableCopy];
NSString * result = [NSString stringWithFormat:@"%@%@",str,oneChar];
[copyArray removeObject:oneChar];
[self __logString:result withLeftArray:copyArray ];
}
}