3089589

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

闲来无事在网上看到一道有趣的算法题,相信很多人都见过,原题如下:

 用1、2、2、3、4、5这六个数字,用java写一个程序,打印出所有不同的排列
 如:512234、412345等,要求:"4"不能在第三位,"3"与"5"不能相连。
 

在网上看到有很多人的答案,有用递归方法来解的,有用无向图连接遍历方法来解的,其实就是一个排列组合的问题,我觉得这道题不论用什么方法来解,最后总会回到递归上,只要将排列组合的算法实现了,那些条件限制无非就是IF ELSE的问题了,在此写下自己的方法,只为以后有需要的时候自己能有些资料复习,别一下子给搞忘了,毕竟是自己写的,熟悉!

public class Main {
	public static void main(String[] args) {
		Main main = new Main();
		String parameter = "122345";
		Set<String> set = main.action(parameter);
		System.out.println("排列数量为:"+set.size());
		for(String s : set){
			System.out.println(s);
		}
	}
	
	private boolean validate(String s){
        if (s.charAt(2) == '4')
            return false;
        if (s.indexOf("35") >= 0 || s.indexOf("53") >= 0)
            return false;
        return true;
	}
	
	/**
	 * 递归调用方法
	 * @param parameter 需要排列的参数
	 * @return 该参数排列所有可能的数组
	 *         因其结果可能有数字的重复,所以采用Set去重
	 */
	private Set<String> action(String parameter){
		//如果参数为1,则返回,
		//每次递归参数的长度会减少1,这是递归的最后结点
		if(parameter.length() == 1){
			Set<String> set = new HashSet<String>();
			set.add(parameter);
			return set;
		}
		//方法返回数组
		Set<String> resultList = new HashSet<String>();
		//循环参数,将其分为两段,一段为单个字符,一段为其余的字符串
		for(int i=0;i<parameter.length();i++){
			//单个字符,如果12345需要排列,首先1不动,2345进行排列
			String s = parameter.substring(i,i+1);
			//其余的字符串
			String rest = parameter.substring(0,i)+parameter.substring(i+1);
			//将其余的字符串递归所得到的数组
			Set<String> list = action(rest);
			//将该单个字符与其余字符串的排列拼起来,既完成了以该字符占第一位,其余字符串进行排列的组合
			for(String str : list){
				StringBuilder sb = new StringBuilder(s.length()+str.length());
				sb.append(s);
				sb.append(str);
				
				if(sb.length() == 6){
					if(validate(sb.toString())){
						resultList.add(sb.toString());
					}
				}else{
					resultList.add(sb.toString());
				}
			}
		}
		return resultList;
	}
}

 

posted on 2013-03-26 09:24  liangge0218  阅读(943)  评论(0)    收藏  举报