【算法-字符串】输出字符串的所有组合

问题描述:

假设字符串中的所有字符不重复,如何输出字符串的所有组合,例如,输入字符串为“abc”,则输出a、b、c、ab、ac、bc、abc,共7种组合。

根据题意,如果字符串中有n个字符,根据排列组合的性质,此时一共需要输出2^n-1种组合。

最容易想到的方式是递归,遍历字符串,每个字符串只能取或不取。若取该字符,就把它放到结果字符串中,遍历完毕后,输出结果字符串。

程序代码为:

public class CombineRecursiveImpl {
	public static void main(String[] args) {
		char[] c=s.toCharArray();
		StringBuffer sb=new StringBuffer("");
		System.out.println(sb);
		int len=c.length;
		for(int i=1;i<=len;i++){
			Solution3.combineRecursive(c, 0, i, sb); 
		}
		
	}
 
}
 
class Solution3{
	public static void combineRecursive(char[] c,int begin,int len,StringBuffer sb){
		if(len==0){
			System.out.print(sb+" ...");
			return;
		}
		if(begin==c.length){
			return;
		}
		sb.append(c[begin]);
		System.out.print(sb+",");
		combineRecursive(c, begin+1, len-1, sb);
		sb.deleteCharAt(sb.length()-1);
		System.out.print(sb+",");
		combineRecursive(c, begin+1, len, sb);
	}
}

输出的结果为: a  b  c  ab  ac  bc abc

采用递归法求解,当n的值不是很大时,不存在效率低下的问题,但当n比较大时,效率会变得很差,因为栈调用次数约为2^n。为了提高效率。我们采用二进制组合算法:

首先我们先实现输出n位二进制的所有组合:

思路解析:假设我们输出3位二进制的所有组合,则组合包括(000,001,010,011,100,101,110,111)这八种情况,我们可以从最低位开始每次加1,则会出现从低到高遇到0变成1,结束,否则遇到1变成0,继续向前反复。当索引index超出数组范围结束输出。

程序代码如下:

public class PrintBinaryClass{
	public static void printBinary(int n){
		char[] c=new char[n];
		for(int i=0;i<n;i++){
			c[i]='0';
		}
		while(true){
			int index=n-1;
			while(c[index]!='0'){
				c[index]='0';
				if(--index<0)
					return;
			}
			c[index]='1';
			String result=new String(c);
			System.out.println(result);
		}
	}
	public static void main(String[] args){
		printBinary(3);
	}
}

考虑本题的特性,可以构造一个长度为n的01字符串(或二进制数)表示输出结果中是否包含某个字符,例如,“001”表示输出结果中不含字符a、b,只含c,即输出结果为c,而“101”,表示输出结果为ac。原题就是要求输出“001”到“111”这2^n-1个组合对应的字符串。

程序代码如下:

public class CombineRecursiveImpl {
 
	public static void main(String[] args) {
		String s="abc";
		char[] c=s.toCharArray();
		Solution4.Combine(c);
	}
 
}
 
class Solution4{
	public static void Combine(char[] c){
		if(c==null){
			return;
		}
		int len=c.length;
		boolean[] used=new boolean[len];
		char cache[]=new char[len];
		int result=len;
		while(true){
			int index=0;
			while(used[index]){
				used[index]=false;
				++result;
				if(++index==len){
					return;
				}
			}
			used[index]=true;
			cache[--result]=c[index];
			System.out.print(new String(cache).substring(result)+" ");
		}
	}
}

运行结果为: a  b   ab c  ac  bc abc

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值