输入一个字符串,输出所有该字符串所有排列情况,如”abc”,有全排列:abc、acb、bac、bca、cab 和cba。
分析:该题有两种解法,一个是递归实现,第二是使用字典序排列。字典序排列的原理主要是把升序的排列(当然,也可以实现为降序)作为当前排列开始,然后依次计算当前排列的下一个字典序排列。对当前排列从后向前扫描,找到一对为升序的相邻元素,记为i和j(i < j)。如果不存在这样一对为升序的相邻元素,则所有排列均已找到,算法结束;否则,重新对当前排列从后向前扫描,找到第一个大于i的元素k,交换i和k,然后对从j开始到结束的子序列反转,则此时得到的新排列就为下一个字典序排列。这种方式实现得到的所有排列是按字典序有序的,这也是C++ STL算法next_permutation的思想。
下面为实现代码:
// [7/7/2013 qingezha] 递归的产生全排列 暂时没弄懂原理
// [9/13/2013 qingezha] 现在已经弄懂了,知道怎么写了,哈哈哈
// 这个接口很重要,对数组arr 下标为k和m之间的元素全排列,思路是这样的:
// 1 递归出口为 k = m 时说明一个全排列已经排好
// 2 从 k 到 m 循环,依次将第一个字符与后面的每一个字符交换,然后全排列后面(k+1,m),然后将交换后的在交换回来,接着交换下一个
void perm(int arr[],int k,int m)
{
if (k==m) //需要判断指针与m,k,提高健壮性
{
for (int i=0;i<m;++i)
{
cout<<arr[i]<<"\t";
}
}
else
{
for(int i=k;i<m;++i) //如1 2 3 4 ;1 和 1 交换,全排列2 3 4
{
swap(arr[k],arr[i]); //交换第k个和从k开始到末尾
perm(arr,k+1,m); //交换后全排列后面的
swap(arr[k],arr[i]);
}
}
}