大致思路:
其实之前一直不能很好地理解全排列,直到看到一个有意思的解释。
全排列是由递归实现的,为了设计递归,只分析“当下”:针对第一个字符,我们有两种选择:第一是把这个字符放到组合中去(每个位置都可以放,所以遍历位置,与之后的每个元素都进行交换);第二是不把这个字符放到组合中去(其实就是和自身交换)。
同理,之后的每个字符都是这样操作。递归实现。临界条件是:当前针对的这个字符到了最后一个,那么此时这个字符串可作为一种可能的结果字符串。
注意点:对于字符串中字符交换函数,记得参数为“引用”类型,因为要实质性地改变字符串;对于结果字符串加入vector存储,要注意避免多个比如“aa”的存储(位置不一样但其实内容一样),方法是用find(查找起始地址,查找结尾地址,要查找的内容)==查找结尾地址 来判断之前不存在该字符串。
AC代码:
class Solution {
public:
vector<string> res;
vector<string> Permutation(string str) {
if(str.size()==0)
return res;
if(str.size()==1)
{
res.push_back(str);
return res;
}
QuanPaiLie(str,0);
//牛客网判题要求按字典序顺序输出
sort(res.begin(),res.end());
return res;
}
void QuanPaiLie(string &str,int begin) //这个str也应该传引用,因为递归过程中要有承接关系,而不是重新创副本
{
if(begin==str.size()-1) //不需要递归了
{
//注意这个判重很容易忽略,不然容易出现多个aa
if(find(res.begin(),res.end(),str) == res.end()) //find从begin搜到end说明搜到最后了都没有
{
res.push_back(str);
return ;
}
}
else //还需要递归
{
for(int i=begin;i<=str.size()-1;i++)
{
swapChar(str,begin,i);
QuanPaiLie(str,begin+1);
swapChar(str,begin,i); //记得换回来!!!
}
}
}
void swapChar(string &str,int a,int b) //加引用哟,因为要实质性改变
{
char temp=str[a];
str[a] = str[b];
str[b] = temp;
}
};