力扣 面試題38. 字符串的排列 dfs+回溯

https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/
在這裏插入圖片描述

思路:dfsdfs+回溯,注意判重即可。
自己實現的究極暴力版本:

class Solution {
public:
    bool vis[8]={0};
    int pos[8]={0};
    vector<string> ans;
    void dfs(int idx,string &s)
    {
        int siz=s.size();
        if(idx==siz)
        {
            string res(idx,' ');
            for(int i=0;i<idx;i++)
                res[i]=s[pos[i]];
            ans.push_back(res);
            return;
        }
        for(int i=0;i<siz;i++)
        {
            if(vis[i])
                continue;
            vis[i]=1;
            pos[idx]=i;
            dfs(idx+1,s);
            vis[i]=0;
        }
    }

    vector<string> permutation(string s) {
        sort(s.begin(),s.end());
        if(!s.size())
            return ans;
        dfs(0,s);
        sort(ans.begin(),ans.end());
        ans.erase(unique(ans.begin(),ans.end()),ans.end());
        return ans;
    }
};

然而這種去重方式太暴力了,我們優化一下,顯然在一次深搜過程中,任意一個字符在位置ii只能出現11次,否則一定會產生重複的情況。這種方式的深搜返回的結果一定是有序的。

class Solution {
public:
    bool vis[8]={0};
    int pos[8]={0};
    vector<string> ans;
    void dfs(int idx,string &s)
    {
        int siz=s.size();
        if(idx==siz)
        {
            string res(idx,' ');
            for(int i=0;i<idx;i++)
                res[i]=s[pos[i]];
            ans.push_back(res);
            return;
        }
        bool check[26]={0};
        for(int i=0;i<siz;i++)
        {
            if(vis[i]||check[s[i]-'a'])
                continue;
            check[s[i]-'a']=1;
            vis[i]=1;
            pos[idx]=i;
            dfs(idx+1,s);
            vis[i]=0;
        }
    }

    vector<string> permutation(string s) {
        sort(s.begin(),s.end());
        if(!s.size())
            return ans;
        dfs(0,s);
        return ans;
    }
};

因爲返回的順序是任意的,所以我們可以選擇交換元素的方式來實現,這種方式結果並不一定有序

class Solution {
public:
    vector<string> ans;
    void dfs(int idx,string &s)
    {
        int siz=s.size();
        if(idx==siz)
        {
            ans.push_back(s);
            return;
        }
        bool vis[26]={0};
        for(int i=idx;i<siz;i++)
        {
            if(vis[s[i]-'a'])
                continue;
            vis[s[i]-'a']=1;
            swap(s[idx],s[i]);
            dfs(idx+1,s);
            swap(s[idx],s[i]);
        }
    }

    vector<string> permutation(string s) {
        sort(s.begin(),s.end());
        if(!s.size())
            return ans;
        dfs(0,s);
        return ans;
    }
};

利用庫函數,快的飛起,而且用這種方式計算出的結果是有序的。

class Solution {
public:
    vector<string> permutation(string s) {
        sort(s.begin(),s.end());
        vector<string> ans;
        do
        {
            ans.push_back(s);
        }while(next_permutation(s.begin(),s.end()));
        return ans;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章