方法一:库函数
1.解题思路
题意:
对于给定字符串,找出它的全排列。
分析:
考察回溯算法
2.解法
这里可使用库函数next_permutation()得到字符串全排列,依次加入数组存储即可
3.具体代码
class Solution { public: vector<string> Permutation(string str) { sort(str.begin(),str.end()); vector<string>ans; ans.push_back(str); while (next_permutation(str.begin(), str.end())){//使用库函数 ans.push_back(str); } return ans; } };
4.时间复杂度和空间复杂度分析
时间复杂度:,字符串全排列总数共,而一次排列用时
空间复杂度:,仅用到vector保存n!个全排列。
方法二:交换回溯
1.解题思路
将字符串转化为字符数组,接着进行交换回溯。每次从根结点到叶子结点的序列即为原序列的一个排列。
2.解法
递归中首先固定某一个下标对应元素,然后将其他元素进行交换。
到叶子节点后返回,接着i++,u比i小1,i与其后面一个元素交换。
注意要用set去重,例如aa,回溯过程会会出现两次aa,所以用set去重后,再加入ans即可。
3.图解
4.具体代码
class Solution { public: set<string>s; void dfs(int u,string &a,int n){//u:当前遍历到字符,a:字符串,n:字符串长度 if(u>n){//递归边界,到达字符串尾 string b;//将当前遍历序列保存为字符串 for(int i=1;i<=n;i++){ b+=a[i]; } s.insert(b);//字符串加入set容器 return; } for(int i=u;i<=n;i++){//遍历序列 swap(a[i],a[u]); dfs(u+1,a,n);//到叶子节点后,u比i小1,i与其后面一个元素交换 swap(a[i],a[u]); } } vector<string> Permutation(string str) { for(int i=str.size();i>=1;i--){//将字符串转化为字符数组,方便接下来操作 str[i]=str[i-1]; } dfs(1,str,str.size());//str.size()是str的最后一个元素 vector<string>ans; for(set<string>::iterator it=s.begin();it!=s.end();it++){//set去重后加入ans ans.push_back(*it); } return ans; } };
5.时间复杂度和空间复杂度分析
时间复杂度:,字符串全排列总数为n!,而递归中嵌套了一个长度为n的循环,所以时间复杂度为O(n*n!)
空间复杂度:,用到了一个大小为n!的set容器及数组。