剑指 Offer 38. 字符串的排列
字符串题目还是经常会遇到。
解法1:递归加去重
先固定一个位置,然后和其他位置的元素交换,依次往后推,当是最后一个时,是返回结果。
class Solution {
public:
vector<string> permutation(string s) {
vector<string> ret;
sort(s.begin(), s.end());
helper(ret, s, 0, s.size() - 1);
return ret;
}
void helper(vector<string>& ret, string& s, int left, int right) {
if (left == right) {
ret.push_back(s);
return;
}
set<int> st;
for (int i = left; i <= right; ++ i) {
if (st.find(s[i]) != st.end()) {
continue;
}
st.insert(s[i]);
swap(s[i], s[left]);
helper(ret, s, left + 1, right);
swap(s[i], s[left]);
}
}
};
[链接](https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/)
解法2:回溯
class Solution {
public:
vector<string> rec;
vector<int> vis;
void backtrack(const string& s, int i, int n, string& perm) {
if (i == n) {
rec.push_back(perm);
return;
}
for (int j = 0; j < n; j++) {
if (vis[j] || (j > 0 && !vis[j - 1] && s[j - 1] == s[j])) {
continue;
}
vis[j] = true;
perm.push_back(s[j]);
backtrack(s, i + 1, n, perm);
perm.pop_back();
vis[j] = false;
}
}
vector<string> permutation(string s) {
int n = s.size();
vis.resize(n);
sort(s.begin(), s.end());
string perm;
backtrack(s, 0, n, perm);
return rec;
}
};
字典序排列
class Solution {
public:
bool nextPermutation(string& s) {
int i = s.size() - 2;
while (i >= 0 && s[i] >= s[i + 1]) {
i--;
}
if (i < 0) {
return false;
}
int j = s.size() - 1;
while (j >= 0 && s[i] >= s[j]) {
j--;
}
swap(s[i], s[j]);
reverse(s.begin() + i + 1, s.end());
return true;
}
vector<string> permutation(string s) {
vector<string> ret;
sort(s.begin(), s.end());
do {
ret.push_back(s);
} while (nextPermutation(s));
return ret;
}
};
Reference
[1] https://wizardforcel.gitbooks.io/the-art-of-programming-by-july/content/01.06.html