1.1 题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
1.2 解题思路
对于全排列问题,不论是字符串的全排列还是数字的全排列,都可以采用回溯法来解决。
核心思想是我们每次递归只确定一个数字的位置。也就是说我们首先固定索引为0的数字,之后我们确定索引为1的数字,一直递归下去,直到整个字符串都被确定那么就得到了全排列的一种排列。
1.3 全排列中的字符不重复 (leetcode 46)
对于不重复的情况比较简单,比如 abc的全排列不会出现重复的情况。代码如下
class Solution {
public:
vector<string> Permutation(string str) {
if(str.size()<=0)
return {};
vector<string> res;
dfs(res,str,0);
return res;
}
void dfs(vector<string>& res,string & str,int start)
{
if(start == str.size()-1)
{
res.push_back(str);
return;
}
for(int i=start;i<str.size();i++)
{
swap(str[i],str[start]);
dfs(res,str,start+1);
swap(str[i],str[start]);
}
}
};
1.4 全排列中包含重复的字符(leetcode 47)
在1.3中给出了全排列的解法,但是对于字符串是‘aa’这种情况,上述解法会得到[‘aa’,‘aa’]也就是会出现重复的情况,因此我们需要对此改进,改进方法也非常简单。 我们需要先对字符串进行排序,之后我们对其进行剪枝操作。
class Solution {
public:
vector<string> Permutation(string str) {
if(str.size()<=0)
return {};
vector<string> res;
sort(str.begin(),str.end()); 先进行排序保证剪枝操作是正确的
dfs(res,str,0);
sort(res.begin(),res.end()); 保证字典序
return res;
}
void dfs(vector<string>& res,string& str,int start)
{
if(start == str.size()-1)
{
res.push_back(str);
return;
}
for(int i=start;i<str.size();i++)
{
if(i>start && str[i] == str[start]) 剪枝操作
continue;
swap(str[i],str[start]);
dfs(res,str,start+1);
swap(str[i],str[start]);
}
}
};