[Mdfs] lc剑指 Offer 38. 字符串的排列(全排列+枚举顺序+组合类型枚举+知识理解+模板题)
Posted Ypuyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Mdfs] lc剑指 Offer 38. 字符串的排列(全排列+枚举顺序+组合类型枚举+知识理解+模板题)相关的知识,希望对你有一定的参考价值。
1. 题目来源
相关:
2. 题目解析
就是个全排列的去重,也可称为组合类型枚举。和 [Mdfs] lc47. 全排列 II(dfs+去重处理+经典) 一模一样。
排序,保证相同元素的相对位置顺序不发生改变就能去重。 基于此,一般可以枚举每个数放的位置,也可以枚举每个位置可以放哪些数。
当然直接使用 next_permutation()
函数也是可以的。
迭代写法就是实现一个 next_permutation()
的操作,[M模拟] lc31. 下一个排列(模拟next_permutation函数+思维) 类比这个模拟实现即可。
在此,给出了本题的两种枚举方式:
- 枚举位置放哪些数
- 枚举数放在哪些位置
这两种枚举方式以及细节,都是为了保证相同数的相对位置不发生改变。
其中,需要特别关注 int u
的含义是截然不同的!
时间复杂度: O ( n ! ) O(n!) O(n!)
空间复杂度: O ( n ) O(n) O(n)
每个位置,可以放哪些数:
这个主要保证:如果前一个数跟当前数相同,但是前一个数还没放置时,那么当前数一定不能放,因为一旦放置的话,我们是顺序枚举位置的,就会造成相对位置发生改变!
class Solution {
public:
vector<string> res;
vector<bool> st;
string path;
void dfs(int u, string s) {
if (u == s.size()) {
res.push_back(path);
return ;
}
for (int i = 0; i < s.size(); i ++ ) {
if (!st[i]) {
if (i && s[i - 1] == s[i] && !st[i - 1]) continue;
path += s[i];
st[i] = true;
dfs(u + 1, s);
st[i] = false;
path.pop_back();
}
}
}
vector<string> permutation(string s) {
sort(s.begin(), s.end());
st = vector<bool>(s.size(), false);
dfs(0, s);
return res;
}
};
每个数,可以放哪些位置:
这个写的比较少,但是也是需要理解,大同小异。需要保证相同数的相对位置不变。如果下一个数和当前数是相同的,那么下一个数的起始位置必须在当前数后,而不能在当前数之前。故需要一个变量记录上一个相同数的放置位置,也就是枚举组合时常见的 start 变量。在枚举下一个相同数时,它的放置位置就只能是 start+1, start+2…,而不能在 start 之前。
class Solution {
public:
vector<string> res;
vector<bool> st;
string path;
void dfs(int u, string s, int start) {
if (u == s.size()) {
res.push_back(path);
return ;
}
for (int i = start; i < s.size(); i ++ ) {
if (!st[i]) {
path[i] = s[u];
st[i] = true;
if (u + 1 < s.size() && s[u + 1] != s[u]) dfs(u + 1, s, 0); // 不同数,下次从 0 开始放
else dfs(u + 1, s, i + 1); // 相同数,只能放到 i 的后面
st[i] = false;
}
}
}
vector<string> permutation(string s) {
sort(s.begin(), s.end());
st.resize(s.size());
path.resize(s.size());
dfs(0, s, 0);
return res;
}
};
库函数
class Solution {
public:
vector<string> permutation(string s) {
sort(s.begin(), s.end());
vector<string> res;
do {
res.push_back(s);
} while(next_permutation(s.begin(), s.end()));
return res;
}
};
以上是关于[Mdfs] lc剑指 Offer 38. 字符串的排列(全排列+枚举顺序+组合类型枚举+知识理解+模板题)的主要内容,如果未能解决你的问题,请参考以下文章
Lc_剑指Offer15二进制中1的个数--------位运算