字符串的排列
描述
输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。
例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。
数据范围:n<10
要求:空间复杂度 O(n!),时间复杂度 O(n!)
输入描述:
输入一个字符串,长度不超过10,字符只包括大小写字母。
示例1
输入:
“ab”
返回值:
[“ab”,“ba”]
说明:
返回[“ba”,“ab”]也是正确的
示例2
输入:
“aab”
返回值:
[“aab”,“aba”,“baa”]
示例3
输入:
“abc”
返回值:
[“abc”,“acb”,“bac”,“bca”,“cab”,“cba”]
示例4
输入:
“”
返回值:
[]
方法一:递归+回溯
思路:
最直接的办法就是固定字符串中一个字符,然后交换另外两个字符,这样从头到尾遍历;用递归:
递归步骤为:
- 设递归函数
dfs(int pos,string s)
表示固定字符串s
下标为pos
的字符是s[pos]
; - 递归终止条件是
pos+1==s.size()
,表示对最后一个字符完成了固定,这样此时可以返回结果s
; - 下一次继续递归
dfs(pos+1,s)
,表示对下一个字符进行固定
但是这样做的结果时会有重复的可能,因此利用集合set
来去重
代码如下:
class Solution {
public:
void perm(int pos,string& s,unordered_set<string>& st){
if(pos+1==s.size()){
st.insert(s);
return ;
}
//例如"ABC"第一次交换'A'和'A'则表示固定'A'
//第二次交换'A'和'B'则表示固定'B'
//第三次交换'A'和'C'则表示固定'C'
for(int i=pos;i<s.size();++i){
swap(s[pos], s[i]);
perm(pos+1, s, st);
swap(s[pos], s[i]);//这里必须回溯,否则会得不到部分结果
}
}
vector<string> Permutation(string str) {
if(str=="") return {};
unordered_set<string> st;
perm(0, str, st);
return vector<string>(st.begin(),st.end());
}
};
- 时间复杂度: O(n!)
- 空间复杂度: O(n!)
方法二:next_permutation
C++11标准库中有一个函数next_permutation()
可以得到当前字符串下一个字典序较大的排列,那么我们只要不断的对字符串进行next_permutation()
就可以获得所有排列,下面介绍next_permutation()
;
next_permutation()
的思想就是从字符串的末尾向前,找到第一个第i
个元素的值小于第i+1
个元素的值,这样从第i+1
个元素到末尾(即[i+1,n)
)构成一个非升序序列;- 然后再从末尾找到第一个大于第
i
个元素值得元素,并交换两者,而且[j+1,n)
上所有元素都不大于第i
个元素的值; - 因此最后只需翻转
[i+1,n)
区间则可以得到字符串字典序的下一个排列,即结果。
class Solution {
public:
vector<string> ans;
vector<string> Permutation(string str) {
if(str=="") return ret;
sort(str.begin(), str.end()); // 一定记住要先排序
do{
ans.push_back(str);
} while(nextPermutation(str));
return ans;
}
bool nextPermutation(string& s){
int i = s.size() - 2; // 从倒数第二个数开始向左搜寻
while(i >= 0 && s[i] >= s[i + 1]) i--;
if(i < 0) return false; // 未找到满足条件的i, 返回false
int j = s.size() - 1;
while(s[j] <= s[i]) j--; // 若i存在, 则j一定存在
swap(s[i], s[j]);
reverse(s.begin() + i + 1, s.end()); // 翻转区间[i + 1, n - 1]
return true;
}
};
- 时间复杂度: 排序的复杂度是O(NlogN),而遍历序列的复杂度是O(N!),因此最后的复杂度为O(N!);
- 空间复杂度: 没有用到额外的空间,为O(1).