【剑指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;
}
}
};
重点思路
细节整理完回溯内容后补充。