枚舉字符串的排列, 八皇后,枚舉&回溯2種解法

輸入一個字符串,打印出該字符串中字符的所有排列。
例如輸入字符串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 ];

    }
    
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章