黑马程序员_求任意字符串及其所有子串的全排列

----------------------  ASP.Net+Unity开发 .Net培训 、期待与您交流! ----------------------
求任意字符串及其所有子串的全排列

        这是我在黑马走流程的基础测试题中的一道,觉得很有意思。于是跟大家分享一下。

/**
 * 第五题:编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符,例如:
 * 原始字符串是"abc",打印得到下列所有组合情况:
 * "a" "b" "c" 
 * "ab" "bc" "ca" "ba" "cb" "ac"
 * "abc" "acb" "bac" "bca" "cab" "cba"
 * @author JunZhu
 */
import java.util.ArrayList;
public class Test5 {
	public static void main(String[] args){
		 //创建一个字符串,并调用allGroups方法输出其全字符组合
		String s="abc";
		System.out.println(s+"的全字符排列组合为:");
		allGroups(s);
	}
	//创建一个方法,用于输出指定字符串的全字符组合
	public static void allGroups(String s){
		//把字符串转换为字符数组
		char[] c=s.toCharArray();
		int l=s.length();
		String[] sc=new String[l];
		//创建一个ArrayList字符串容器al
		ArrayList<String> al=new ArrayList<String>();
		//给集合al和字符串数组sc赋初始值
		for(int a=0;a<l;a++){
			sc[a]=String.valueOf(c[a]);
			al.add(sc[a]);
		}
		//while循环,判断条件为组合的长度是否到了最大值
		while(al.get(al.size()-1).length()<l){
			//al2用于临时存放当前长度的字符串的所有可能组合
			ArrayList<String> al2=new ArrayList<String>();
			//for循环表示,当首字符为sc[i]时,当前长度字符串的所有可能组合
			for(int i=0;i<l;i++){
				//这个增强for循环用来取al中的字符串,当满足不重复的条件时,就与首字符sc[i]进行组合
				for(String s1:al){
					if(s1.contains(sc[i])||al.get(al.size()-1).length()!=s1.length()) continue;
					al2.add(sc[i]+s1);
				}
			}
			//将当前长度字符串的所有组合存入al中,之后进入下一个长度的排列组合
			for(String s2 : al2) al.add(s2);
		}
		//输出al中的所有组合,由于ArrayList是有序的,因此可以按照组合字符串中字符个数按行输出
		int b=1;
		for(String s3:al){
			if(s3.length()!=b) System.out.println();
			System.out.print(s3+"\t");
			b=s3.length();
		}
	}
}
原理是先求含1个字符的子串,然后将字符串中不同字符放在首位分别与子串组合,得到长度为2的所有子串的排列组合,然后 将字符串中不同字符放在首位分别与长度为2的所有子串的排列组合再组合,得到长度为3的所有子串的排列组合.以此类推。根据这个算法,我又写了个使用递归来实现的程序,代码如下。

/**
 * 第五题:编程列出一个字符串的全字符组合情况,原始字符串中没有重复字符,例如:
 * 原始字符串是"abc",打印得到下列所有组合情况:
 * "a" "b" "c" 
 * "ab" "bc" "ca" "ba" "cb" "ac"
 * "abc" "acb" "bac" "bca" "cab" "cba"
 * @author JunZhu
 */
import java.util.ArrayList;
public class test5 {
	public static void main(String[] args){
		 //创建一个字符串,并调用allGroups方法输出其全字符组合
		String s="abcd";
		System.out.println(s+"的全字符排列组合为:");
		ArrayList<String> al=new ArrayList<String>();
		ArrayList<String> al2=new ArrayList<String>();
		char[] c=s.toCharArray();
		int l=s.length();
		String[] sc=new String[l];
	//创建一个ArrayList字符串容器al
	//ArrayList<String> al=new ArrayList<String>();
	//给集合al和字符串数组sc赋初始值
		for(int a=0;a<l;a++){
			sc[a]=String.valueOf(c[a]);
			al.add(sc[a]);
		}
			al2=allGroups(sc,al,al.size(),s);
			int b=1;
			for(String s3:al2){
				if(s3.length()!=b) System.out.println();
				System.out.print(s3+"\t");
				b=s3.length();
			}
	}
	//创建一个递归方法,用于输出指定字符串的全字符组合
	public static ArrayList<String> allGroups(String[] sc,ArrayList<String> al,int l,String s){
		if(l>1){
			ArrayList<String> al1=new ArrayList<String>();
			ArrayList<String> al2=new ArrayList<String>();
			al1=allGroups(sc,al,l-1,s);
			for(int i=0;i<s.length();i++){
			for(String s1:al1){
				if(s1.contains(sc[i])||al1.get(al1.size()-1).length()!=s1.length()) continue;
				al2.add(sc[i]+s1);
			}
		}
			for(String s2 : al2) al1.add(s2);
			return al1;
	}
		return al;
	}
}
同一个需求,可以有很多的算法实现,同一个算法,可以有不同的语言不同的形式实现。

后来我又看见一种算法。

import java.util.*;
public class StringPaiLie
{
        public static void main(String[] args)
        {
                showPermString("abc");
        }                        
        public static void showPermString(String str)
        {
                for(int i=1; i<=str.length(); i++)//str.length()
                {
                        List<String> list = new ArrayList<String>();
                        perm(list, str.toCharArray(), 0, i);
                        System.out.println(list);
                }
        }
        public static void perm(List<String> list,char[] chs,int k,int len)
        {
                if(k == chs.length)
                {
                        String string = String.valueOf(chs, 0, len);
                        if(!list.contains(string))
                                list.add(string);
                }
                else
                {
                        for(int i=k; i<chs.length; i++)
                        {                        	
                                swap(chs, i, k);                      
                                perm(list,chs, k+1,len);
                                swap(chs, i, k);                              
                        }
                }     
        }        
        public static void swap(char[] chs,int i,int j)
        {
                char tem = chs[i];
                chs[i] = chs[j];
                chs[j] = tem;
        }
}
首先这个程序是用递归实现字符串及其子串的全排列。其实只要理解了perm方法其他的就差不多了。perm使用递归实现一个字符串的全排列。然后showPermString方法每次循环截取一定的长度,就成了它相应子串的全排列。也就是说它求子串全排列的时候,也是把整串的全排列求出来,截取从0到len的一段,因为整串的全排列肯定包含了其所有子串的全排列。但是这样效率很低。当字符串在“abcdefghi”这样长度的时候,这个程序的速度跟最上面的程序差距就很明显了。



---------------------- ASP.Net+Unity开发.Net培训、期待与您交流! ----------------------
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值