【算法】字符串的全排列

from https://github.com/julycoding/The-Art-Of-Programming-By-July/blob/master/ebook/zh/01.06.md

题目描述

输入一个字符串,打印出该字符串中字符的所有排列。

例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串

abc、acb、bac、bca、cab 和 cba。

解法一、递归实现

从集合中依次选出每一个元素,作为排列的第一个元素,然后对剩余的元素进行全排列,如此递归处理,从而得到所有元素的全排列。以对字符串abc进行全排列为例,我们可以这么做:以abc为例

  • 固定a,求后面bc的排列:abc,acb,求好后,a和b交换,得到bac
  • 固定b,求后面ac的排列:bac,bca,求好后,c放到第一位置,得到cba
  • 固定c,求后面ba的排列:cba,cab。

#include "stdafx.h"
#include "stdio.h"
#include "iostream"
using namespace std;
//字符串的全排列
void CalcAllPermutation(char* perm, int from, int to)
{
	if (to <= 1)
	{
		return;
	}
	int i,j;
	if (from == to)
	{
		for(i = 0;i <= to;i++)
		{
			cout<<perm[i];
		}
		cout<<endl;
	}
	else
	{
		for (j = from ;j<=to;j++)
		{
			swap(perm[j], perm[from]);
			CalcAllPermutation(perm, from + 1, to);
			swap(perm[j], perm[from]);
		}
	}
	
}

解法二、字典序排列

next_permutation算法

  • 定义

    • 升序:相邻两个位置ai < ai+1,ai 称作该升序的首位
  • 步骤(二找、一交换、一翻转)

    • 找到排列中最后(最右)一个升序的首位位置i,x = ai
    • 找到排列中第i位右边最后一个比ai 大的位置j,y = aj
    • 交换x,y
    • 把第(i+ 1)位到最后的部分翻转

还是拿上面的21543举例,那么,应用next_permutation算法的过程如下:

  • x = 1;
  • y = 3
  • 1和3交换
    • 得23541
  • 翻转541
    • 得23145

23145即为所求的21543的下一个排列。参考实现代码如下:

bool CalcAllPermutation_dict(char* perm, int num){
	int i;

	//①找到排列中最后(最右)一个升序的首位位置i,x = ai
	for (i = num - 2; (i >= 0) && (perm[i] >= perm[i + 1]); --i){
		;
	}
	// 已经找到所有排列
	if (i < 0){
		return false;
	}

	int k;
	//②找到排列中第i位右边最后一个比ai 大的位置j,y = aj
	for (k = num - 1; (k > i) && (perm[k] <= perm[i]); --k){
		;
	}

	//③交换x,y
	swap(perm[i], perm[k]);
	//④把第(i+ 1)位到最后的部分翻转
	reverse(perm + i + 1, perm + num);
	return true;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值