字符串的排列


title: 2019-8-24 字符串的排列
tags: 算法,每日一題,字符串


字符串的排列

1. 題目描述

輸入一個字符串,按字典序打印出該字符串中字符的所有排列,輸入一個字符串,長度不超過9(可能有字符重複),字符只包括大小寫字母。例如輸入字符串abc,則打印出由字符a,b,c所能排列出來的所有字符串abc,acb,bac,bca,cab和cba。

2.題目解析

首先對於給定的一個字符串比如abc,對於第一個位置我們可以有三種選擇,a,b,c。所以只需要每次都把字符串對應的字符換到第一個位置即可。比如現在我們把b換到了第一個位置bac,那麼這個時候相當於固定了第一個位置的字符了,對於後面的字符的處理就和之前的一樣了(ok構成了遞歸了)。因此只要遞歸下去就可以解決問題了。但是這是沒有考慮字符串中有重複元素的情況。

對於字符串中包含重複字符的情況,我們可能會嘗試如果要交換的字符相同的我們就不交換,但是對於abb ,第一次aa交換不變,第二次ab交換得到bab,第三次bba。顯然第三次的遞歸會得到一個bba的結果,第二次的bab也會得到一個bba的結果。所以這種嘗試是無效的。現在嘗試策略二:在當前這次遞歸中,如果從from到當前交換的位置之間都沒有相同的元素(保證之前沒有出現固定當前元素的情況)。

這兩個問題解決之後還有一個問題就是按照字典序輸出,這需要在每次進行下一次遞歸之前對從from到to之間的元素進行一次字典排序即可。

2.1 思路解析

1、只考慮全排列的情況

2、考慮用重複的情況

錯誤的方式,相同的字符不交換

正確的情況:從交換位置處ifrom之間如果有和i相同的字符就不交換也不會遞歸下去

3、需要字典排序的字符串全排列

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> res;
        if(str.empty()) return res;
        sort(str.begin(), str.end());
        permutation_recru(str, 0, str.size()-1, res);
        return res;
    }
    
    void permutation_recru(string& str,int from, int to, vector<string>& res){
        if(from == to) {
            res.push_back(str);
            return;
        }
        for(int i=from; i<=to; ++i){
            sort(str.begin() + from, str.end());//這個只能放在這個位置
            if(isSwap(str, from, i)){
                swap(str, from, i);
                permutation_recru(str, from+1, to, res);
                swap(str, from, i);
            }
        }
    }
    
    void swap(string& str, int a, int b){
        char temp = str[a];
        str[a] = str[b];
        str[b] = temp;
    }
    
    bool isSwap(string& str, int from, int to){
        for(int i=from; i<to; ++i){
            if(str[i] == str[to]) return false;
        }
        return true;
    }
};

更多關於編程和機器學習資料請關注FlyAI公衆號。
公衆號二維碼

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