【剑指Offer-38】字符串的排列

问题

输入一个字符串,打印出该字符串中字符的所有排列。

你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。

示例

输入: s = "aab"
输出: ["aab","aba","baa"]]

解答1:swap解决全排列

class Solution {
public:
    vector<string> permutation(string s) {
        recur(s, 0);
        return res;
    }
private:
    vector<string> res;
    void recur(string& s, int pos) {
        if (s.size() == pos) res.push_back(s);
        for (int i = pos; i < s.size(); i++) { 
            if (checkDup(s, pos, i)) continue;
            swap(s[i], s[pos]);
            recur(s, pos + 1);
            swap(s[i], s[pos]);
        }
    }
    bool checkDup(string& s, int pos, int i) {
        for (int j = pos; j < i; j++) 
            if (s[j] == s[i]) return true;
        return false;
    }
};

重点思路

经典的回溯题,使用swap函数遍历同深度的所有可能情况,backTrace函数进入下一个深度,最后再swap回来实现回溯功能。本题需要注意的是可能存在重复元素,所以需要在深度优先遍历中剪枝,如下图所示。

使用set等数据结构来进行剪枝会花费更多的内存,这里采用for循环直接判断是否需要剪枝。

解答2:回溯模版

class Solution {
public:
    vector<string> permutation(string s) {
        sort(s.begin(), s.end());
        vis.resize(s.size());
        backTrace(s);
        return res;
    }
private:
    string ans;
    vector<int> vis;
    vector<string> res;
    void backTrace(string& s) {
        if (s.size() == ans.size()) res.push_back(ans);
        for (int i = 0; i < s.size(); i++) {
            if (vis[i]) continue;
            if (i > 0 && s[i] == s[i - 1] && vis[i - 1]) break;
            vis[i] = 1;
            ans.push_back(s[i]);
            backTrace(s);
            ans.pop_back();
            vis[i] = 0;
        }
    }
};

重点思路

细节整理完回溯内容后补充。

posted @ 2021-03-03 18:05  tmpUser  阅读(36)  评论(0编辑  收藏  举报