【剑指Offer-分解让复杂问题简单化】面试题38:字符串的排列

题目描述

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
牛客网输入:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
注:牛客网的输入可能有字符重复,而书上是没有重复字符的。

思路1

可以模拟人来做排列的情形,比如3个字符a、b和c。第一个字符有3种选择:a、b或者c,当第一个字符确定之后,第二个字符有2种选择,当前两个字符确定之后,最后一个字符也确定了。使用循环和递归来模拟这一过程,代码如下:

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> ans;
        if(str=="")
            return ans;
        
        int visit[str.length()];
        memset(visit, 0, sizeof(visit));
        string cur;
        PermutationCore(str, ans, cur, visit);
        ans = RemoveRepeat(ans);
        return ans;
    }
    
    void PermutationCore(string str, vector<string>& ans, string cur, int* visit){
        if(cur.length()==str.length()){
            ans.push_back(cur);
            return;
        }
        
        for(int i=0; i<str.length(); i++){
            if(!visit[i]){
                visit[i] = 1;
                cur+=str[i];
                PermutationCore(str, ans, cur, visit);
                cur = cur.substr(0, cur.length()-1);    //把前一步加的字符删掉
                visit[i] = 0;
            }
        }
    }
    
    vector<string> RemoveRepeat(vector<string> ans){
        set<string> s;
        for(int i=0; i<ans.size(); i++)
            s.insert(ans[i]);
        
        vector<string> newAns;
        for(set<string>::iterator it=s.begin();it!=s.end(); it++)
            newAns.push_back(*it);
        return newAns;
    }
};

由于牛客网的输入可能包含重复数字,最终的输出中也包含重复的排列,所以添加了一个去重的函数RemoveRepeat,去重的思路是将所有排列放到set中,set中的元素都是唯一的,然后再把set中的元素放到vector中返回。

思路2

第2个思路就是书上的方法,将求整个字符串的排列分为2步:第一求所有可能出现在第一个位置的字符,也就是将第一个字符与后面所有字符交换;第二步,固定第一个字符,重复第一步的过程。代码如下:

class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string> ans;
        if(str=="")
            return ans;
        
        int cur = 0;
        PermutationCore(str, ans, cur);
        ans = RemoveRepeat(ans);
        return ans;
    }
    
    void PermutationCore(string str, vector<string>& ans, int cur){
        if(cur==str.length()){
            ans.push_back(str);
            return;
        }
        
        for(int i=0; i<str.length(); i++){
            swap(str, i, cur);
            PermutationCore(str, ans, cur+1);
            swap(str, i, cur);
        }
    }
    
    void swap(string& str, int a, int b){
        char t = str[a];
        str[a] = str[b];
        str[b] = t;
    }
    
    vector<string> RemoveRepeat(vector<string> ans){
        set<string> s;
        for(int i=0; i<ans.size(); i++)
            s.insert(ans[i]);
        
        vector<string> newAns;
        for(set<string>::iterator it=s.begin();it!=s.end(); it++)
            newAns.push_back(*it);
        return newAns;
    }
};
posted @ 2020-03-15 21:13  Flix  阅读(121)  评论(0编辑  收藏  举报