题目描述:
输入一个字符串,打印出该字符串中字符的所有排列。
你可以以任意顺序返回这个字符串数组,但里面不能有重复元素。
示例:
输入:s = “abc”
输出:[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
限制:
1 <= s 的长度 <= 8
解题思路:
利用dfs枚举每个位置即可.
先遍历一遍整个字符串, 用map<string,int>记录出现的字符以及字符的个数.
这里需要的注意的, 和之前dfs不同的是 这里要增加一个恢复现场的步骤.
/*枚举pos位置上的字符*/
for (auto it = hash.begin(); hash.end() != it; ++it) {
if (it->second == 0)
continue;
string tmp = str + it->first;
it->second--;
dfs(pos + 1, tmp, hash);
it->second++; // 恢复现场
}
原因:
比如我们枚举pos = 0的位置,
可选的字符有三个: a, b, c
_,_,_
首先pos = 0的位置为a, 进入下层dfs
到 pos = 1 时 还有两个字符可以选 b,c
… …
当pos = 0位置为a的全部情况枚举完了之后.
再次枚举pos = 0位置为b的所有情况, 那么这个时候 就要把上次拿走的a再还回来, 才能正常枚举, 不然只剩下2个字符了.
ac代码:
class Solution {
public:
vector<string> result;
unordered_set<string> vis;
int size;
void dfs(int pos, string str, map<string,int> hash) {
if (pos == size) {
cout << str << endl;
if (!vis.count(str)) {
result.push_back(str);
vis.insert(str);
}
}
/*枚举pos位置上的字符*/
for (auto it = hash.begin(); hash.end() != it; ++it) {
if (it->second == 0)
continue;
string tmp = str + it->first;
it->second--;
dfs(pos + 1, tmp, hash);
it->second++;
}
}
vector<string> permutation(string s) {
int i, j;
size = s.size();
map<string,int> hash;
for (i = 0; i < s.size(); ++i) {
string tmp = "";
tmp += s[i];
auto it = hash.find(tmp);
if (hash.end() == it) {
hash[tmp] = 0;
}
++hash[tmp];
}
dfs(0, "", hash);
return result;
}
};