基本思想
嗯,一拿到这个题目,没有马上想到思路。查看其他人的博客,才理解一点。
- 先找出所有可能出现在第一个位置的字符的情况
- 固定好第一个位置的字符
- 第一个位置上的字符固定后,用同样的方式对第二个位置以后的字符串进行排列(递归求解)
请注意,每一次在第一步时候,同一层递归函数的的字符串在交换字符前是一样的pos位置上的字符是一样的,所以第一步中,第一次交换了一个字符swap(str[pos],str[i]),递归得到str[i]在第一个位置pos时的字符串后,要把str[pos]和str[i]交换回去,接着再用下一个str[i](i++)与str[pos]交换,求出以新的str[i]开头的字符串的排列形式。
代码中用到了set,相关介绍,可以参考其他博主:链接: https://blog.csdn.net/u_nravel/article/details/80425387.
代码
void perm(string str,int pos,set<string>& res ){
if(pos+1==str.size()){//当前这种字符的排列已经排到最后一个位置了,即已经确定了字符串的一种排列形式,将该种排列的字符串加入到结果
res.insert(str);
return;
}
//求出所有可能出现在第一个位置的字符 swap,交换位置
for(int i=pos;i<str.size();i++){
swap(str[pos],str[i]);//把可能出现在pos位置的字符依次放上去
//固定好pos上的字符后,以同样的方式排列pos+1到n的字符串
perm(str,pos+1,res);
swap(str[pos],str[i]);//将刚刚换到pos位置上字符换回到原始位置,保持原始字符的排列形式,for循环开始交换下一个字符
}
}
vector<string> Permutation(string str) {
set<string> res;
perm(str,0,res);
return vector<string> ({res.begin(),res.end()}) ;
}
总结
题目到手时,一头雾水,毫无头绪…看了别人的代码才知道要这样想:每次先固定某一个位置上的字符,然后再缩小范围,递归求解,编程路上,砥砺前行~