内容会持续更新,有错误的地方欢迎指正,谢谢!
题目
题目描述:
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
输入描述:
输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。
分析
一下子想不出解决方案就举例+画图+分解!
如图所示,便是我们的思路。
所以,求所有字符的排列的步骤:
1.求出所有可能出现在第一个位置的字符,即把第一个字符依次和后面的每个字符交换。
2.固定第一个字符,求剩下的所有字符的排列。
看到没,开始递归了。
递归实现的代码
class Solution {
private:
vector<string> res;
public:
void Permu(string str,int begin)
{
int sSize=str.size();
//begin指向当前执行排列的字符串的第一个字符(即“名义上的第一位”),直到begin指向字符串的末尾
if(begin==sSize)
{
res.push_back(str);
return;
}
for(int i=begin;i<sSize;++i)
{
//若要交换的字符相同就跳过,因为i和begin相等时已计算过此种情况了,否则会重复输出部分结果。
if(i==begin||str[i]!=str[begin]) //等价于if(i!=begin&&str[i]==str[begin])
{
swap(str[i],str[begin]);//<algorithm>头文件里的交换函数,用于“名义上的第一位”和后面某一位交换
//将“名义上的第一位”固定住,再对剩下的元素进行排列操作,人脑跑递归时,可先忽略递
//归调用,先执行for循环,再针对每次for循环的结果,将递归函数看成求解这种情况的一
//个方法,这个方法又会调用这个方法,直到满足前面的结束条件便输出一个字符串。
Permu(str,begin+1);//不能用++begin和begin++
}
}
}
vector<string> Permutation(string str)
{
int sSize=str.size();
if(sSize!=0)
Permu(str,0);
return res;
}
};
调用next_permutation实现的代码
在STL里,next_permutation(str.begin(),str.end())
是求出下一个排列组合,而prev_permutation(str.begin(),str.end())
是求出上一个排列组合。所谓“下一个”和“上一个”。
虽然最后一个排列理论上没有下一个排列,且next_permutation
会返回false,但此时使用了这个next_permutation
方法后,序列会变成字典序列的第一个,如cba变成abc。prev_permutation
同理。
用next_permutation
和prev_permutation
求排列组合问题很方便,但是要记得包含头文件#include <algorithm>
。
class Solution//默认引入了<algorithm>
{
private:
vector<string> res;
public:
vector<string> Permutation(string str)
{
int sLength=str.size();
if(sLength==0)
return res;
sort(str.begin(),str.end());
do//do-while循环和next_permutation、prev_permutation更配喔~
{
res.push_back(str);
}while(next_permutation(str.begin(),str.end()));
//next_permutation()执行一次 当前的str序列abc 就变成了 升序中的下一个str序列acb
//当 当前的str序列 是 最后一种str序列cba ,那么它就会变成最初的str序列abc
return res;
}
};
补充两道简单的练手题:
1.dceb的下一个序列分别是什么呢?
解答:用一次next_permutation
就解决了!
2.dceb的上一个序列分别是什么呢?
解答:用一次prev_permutation
就解决了!