字符串--2-字符串全排列

转载:

全排列参考

Jack aci
  1. 问题描述:输入一个字符串,输出该字符串所有可能的排列方式(全排列);

  2. 问题解析:

    字符串全排列问题算是一种找规律的问题,若果我们能找到生成第一个字符排列的方法,那么参考这个方法就可以依次生成其余的字符串排列,不过得强调一点,找到的这个方法必须得满足正确性、互异性和完整性,否则就不能称得上是全排列了。

    按照每个人的不同思维习惯,字符串全排列的生成方法应该是多样的,有的人喜欢从后往前生成新的排列,有的人偏爱于依次将单个字符插入不同位置来生成新的序列,博主将用下面这个例子阐述一下自己的思路。

    全排列讲解图片

    如上图所示,我们以 {a,b,c,d} 为例:

    • 从第一列开始,我们将“a”与自身和其它字符依次交换位置(绿色为交换位置的两个字符),生成第二列中的四个新的子串;

    • 到了第二列中,我们将第一位固定不动(橘黄色为固定不动的字符位),将剩下的三个字符视为新的字符串,新的字符串重复由第一列到第二列的操作。如“b”分别与“自身”、“c”、“d”进行位置交换,生成第三列;

    • 到了第三列,固定不动的位数加一,即前两位不动,剩下的两个字符视为新的字符串,重复之前的字符交换操作,生成第四列;

    • 到了第四列,固定不动的位数加一,前三位不再参与字符交换,剩下的一位字符再进行交换将毫无意义,排列结束;

    • 至此,{a,b,c,d} 生成全部的字符排列。

  3. 程序设计:

    有了好的思路,得想办法转化为可运行的程序化过程,如下:

    • 上述排序算法中,随着单个字符与其它字符的依次交换,会存在一些固定不动的点,这些点是不参与下一轮字符交换的,那么我们只需要将可操作的片段传入下一步;

    • 假设待排序字符串为“Str[n]”,初始可操作片段为整个字符串,我们将(0,n-1)传入下一步,并将第一个操作字符设置为指定交换字符;

    • 设传入的代码片段为(m,n-1),若指定交换字符为“n-1”,则将“m-1,n-1”传给自己,并将“m”设为指定交换字符(在这里,如果“m-1”小于“0”,则跳到最后一步);若指定交换字符不为“n-1”,将“m”与指定的交换字符进行位置交换,将新生成的代码片段传入下一步;

    • 设传入的代码片段为(m,n-1),若该可操作片段长度为“1”,即“m”与“n-1”同字符,输出“Str[n]”,并把(m-1,n-1)传回上一步,将“m-1”设为指定交换字符;若可操作片段长度大于“1”,则把(m+1,n-1)传回上一步,将“m+1”设为指定交换字符;

    • 至此,已生成字符串“Str[n]”的全部排列。

分别把第一个字符a和后面的b、c等字符交换的情形。首先固定第一个字符,求后面所有字符的排列。这个时候我们仍把后面的所有字符分为两部分:后面的字符的第一个字符,以及这个字符之后的所有字符。然后把第一个字符逐一和它后面的字符交换。


#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
public:
	vector<string> permutation(string str)
	{
		if (str.size() <= 0)
			return result;

		permutationCore(0, str);

		return result;
	}

private:
	void permutationCore(int begin, string str)
	{
		if (begin == str.size())
		{
			result.push_back(str);
			cout << str << endl;
			return;
		}
		for (int i = begin; i < str.size(); i++)
		{
			if (begin != i && str[begin] == str[i])
				continue;

			swap(str[begin], str[i]);

			permutationCore(begin + 1, str);
		}
	}
	vector<string> result;
};

int main()
{
	Solution s;
	string str = "abcd";
	vector<string> strResult = s.permutation(str);

	/*for (int i = 0; i < strResult.size(); i++)
		cout << strResult[i] << endl;*/

	system("pause");
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值