字符串全排列问题 java语言实现

要准备找工作了,得开始复习数据结构和算法基础了,最近看到全排列的问题,百度一下,看到了一博主依据交换的思想用c++实现了全排列。参见

1.不重复字符串获取全排列

个人觉得这种交换的思想相对还是难懂一点,不妨再换一种思维方式,以使得算法更加的“递归”。

思考:

要获取字符串s的全排列,就是从s中抽取一个子字符之后,再获取从s中除去该字符的字串s1的全排列。这样一想,岂不是更加容易理解,更加递归。下面贴出java版的源代码。

	/**
	 * 获取一个字符串的全排列,设置两个参数是为了方便递归
	 * @param done	已经排列好的部分
	 * @param toBeDone	未排列好的部分
	 */
	public void getFullPermutation(char []done,char []toBeDone){
		if(toBeDone.length==0){
			System.out.println(new String(done));
			return ;
		}
		for(int i=0;i<toBeDone.length;i++){
			char []newDone=new char[done.length+1];
			char []newToBeDone=new char[toBeDone.length-1];
			//增加一个元素
			System.arraycopy(done, 0, newDone, 0, done.length);
			newDone[done.length]=toBeDone[i];
			//减去一个元素
			System.arraycopy(toBeDone, 0, newToBeDone, 0, i);
			System.arraycopy(toBeDone, i+1, newToBeDone, i, toBeDone.length-i-1);
			getFullPermutation(newDone,newToBeDone);
		}
	}
上述代码中使用了System的arrayCopy函数来拷贝数组

2.重复字符串获取全排列

对于重复的字符串,上述方法则会产生重复的排列,原因是:例如对于字符串abbc,加入现在要获取长度为3的子字符串的全排列,则会在取出一个字符b后,两次对子字符串abc进行全排列运算。

解决的思路是:

对待排序的字符串进行排序,这样相同的字符串就会挨在一起,接着在获取子字符串的全排列之前,先检查这个子字符串是否与上一个进行全排序的子字符串相同,如果相同,则跳过,不获取该子字符串的全排列,否则获取。
代码如下:
	/**
	 * 获取一个字符串的全排列,设置两个参数是为了方便递归,第一次运算时,第一个参数应当设置为new char[0]
	 * @param done	已经排列好的部分
	 * @param toBeDone	未排列好的部分
	 */
	public void getNonRepeatFullPermutation(char []done,char []toBeDone){

		//长度为0,表示首次进行运行,则先对字符串进行排序
		if(done.length==0){
			Arrays.sort(toBeDone);
		}
		char []lastToBeDone=null;
		for(int i=0;i<toBeDone.length;i++){
			char []newDone=new char[done.length+1];
			char []newToBeDone=new char[toBeDone.length-1];
			//增加一个元素
			System.arraycopy(done, 0, newDone, 0, done.length);
			newDone[done.length]=toBeDone[i];
			//减去一个元素
			System.arraycopy(toBeDone, 0, newToBeDone, 0, i);
			System.arraycopy(toBeDone, i+1, newToBeDone, i, toBeDone.length-i-1);
//			if(lastToBeDone==null||!new String(lastToBeDone).equals(new String(newToBeDone))){
			if(!Arrays.equals(lastToBeDone, newToBeDone))
				getNonRepeatFullPermutation(newDone,newToBeDone);
				lastToBeDone=newToBeDone;
			}
		if(toBeDone.length==0){
			System.out.println(new String(done));
			return ;
		}
	}
上述代码中的注释部分的意思是:如果先对字符串数组进行排序,那么在后面判断子字符串是否已经进行过全排列时,就不必使用Arrays.equals来比较所含的字符是否一样,而直接可以使用String().equals方法来比较字符串是否相等(因为待进行全排列的字符串是进行排序过得),很明显后者的计算速度比前者快。

顺便贴出用jUint 4进行单元测试的代码(强烈建议在练习时使用jUint4进行测试,而不是编写main函数)
	@Test
	public void testGetFullPermutation(){
		char []c=new char[]{'a','b','c','d','e','f','g'};
		System.out.println("开始查找");
		a.getFullPermutation(new char[0],c);
	}
	
	@Test
	public void testGetNonRepeatFullPermutation(){
		char []c=new char[]{'a','b','b','c'};
		System.out.println("开始查找");
		a.getNonRepeatFullPermutation(new char[0],c);
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值