回溯 + set集合:
选择一个位置的字符后向后互换,遇到相同的字符直接跳过,通过 set 判断字符是否相同,递归到最后一个字符则成为一个字符串
class Solution {
public:
vector<string> permutation(string s) {
dfs(s, 0);
return res;
}
void dfs(string& s, int index) {
if (index == s.size() - 1) {
res.push_back(s);
return;
}
set<char> record;
for (int i = index; i < s.size(); ++i) {
if (record.find(s[i]) == record.end()) {
record.insert(s[i]);
std::swap(s[index], s[i]);
dfs(s, index + 1);
std::swap(s[index], s[i]);
}
}
}
private:
vector<string> res;
};
时间复杂度:,第一个n为字符串长度,每个字符递归都有for循环,for循环按照字符数量递减,循环次数也递减n x (n - 1) x ... x 1,所以是 n 的阶乘,且每个循环都会查询 set集合,而 set 集合的查询速度是 log (n)
空间复杂度:,递归全排列深度为n,累计使用栈空间大小为,递归辅助 set 存储数据量为 n + (n - 1) + ... + 1 = n x (n + 1) / 2,所以是加上,也是
回溯 + 条件判断:
选择一个位置的字符后向后互换,遇到相同的字符直接跳过,自己写循环判断当前值是否在之前出现过,如果出现了则不交换
class Solution {
public:
vector<string> permutation(string s) {
dfs(s, 0);
return res;
}
void dfs(string& s, int index) {
if (s.size() - 1 == index) {
res.push_back(s);
}
bool flag;
for (int i = index; i < s.size(); ++i) {
flag = true;
for (int j = index; j < i; ++j) {
if (s[j] == s[i]) {
flag = false;
}
}
if (flag) {
swap(s[i], s[index]);
dfs(s, index + 1);
swap(s[i], s[index]);
}
}
}
private:
vector<string> res;
};
时间复杂度:,第一个n为字符串长度,每个字符递归都有for循环,for循环按照字符数量递减,循环次数也递减n x (n - 1) x ... x 1,所以是 n 的阶乘,每个循环会有一个查询字符是否重复的 for循环,这个循环的时间是
空间复杂度:,递归全排列深度为n,累计使用栈空间大小为,递归使用 bool 变量 每个递归有一个 bool 值 因此是