Java实现:按要求打印数组的排列情况

问题描述:针对1、2、2、3、4、5 这6个数字,写一个函数,打印出所有不同的排列,例如512234、215432等,要求“4”不能在第三位,“3”与“5”不能相连。

打印数组的排列组合方式最简单的方法就是递归,但本题有两个难点:第一,数字中存在重复数字;第二,明确规定了某些位的特性。采用常规的求解方法似乎不能完全适用了。

换一种思维,把求解这6个数字的排列组合转换为大家熟悉的图的遍历问题,解答起来就容易多了,可以把1、2、2、3、4、5 这6个点看作图的6个结点,对6个结点两两相连可以组成一个无向连通图,这6个数字对应的全排列等价于从这个图中各个结点出发深度遍历这个图所有可能路径所组成的数字集合,例如,从结点1出发的所有遍历路径组成了以1开头的所有数字的组合。由于“3”与“5”不能相连,因此在构造图时使图中3和5对应的结点不连通就可以满足这个条件。对应“4”不能在第三位,可以在遍历结束后判断是否满足这个条件。

具体步骤如下:

(1)、用1、2、2、3、4、5 这6个数字作为6个结点,构造一个无向连通图。除了“3”与“5”不连通外,其它所有结点都两两相连。

(2)、分别从这6个结点出发对图做深度优先遍历。每次遍历完所有结点,把遍历的路径对于数字的组合记录下来,若这个数字的第三位不是“4”,则把这个数字存放到集合Set中(由于这6个树中有重复的数,因此最终的组合肯定也会有重复的。由于集合Set的特点为集合中的元素是唯一的,不能有重复的元素,因此通过把组合的结果放到Set中可以过滤掉重复的组合。)

(3)遍历Set集合,打印出集合中的所有结果,这些结果就是本问题的答案。

实现代码如下:
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class GetAllCombination {
	public static void main(String[] args) {
		Solution5 ss=new Solution5();
		Set<String> set=ss.getAllCombination();
		Iterator<String> it=set.iterator();
		while(it.hasNext()){
			String string=(String)it.next();
			System.out.println(string);
		}
	}

}
class Solution5{
	private int[] numbers=new int[]{1,2,2,3,4,5};
	private int n=numbers.length;
	//用来标记图中结点是否被标记过
	private boolean[] visited=new boolean[n];
	//图的二维数组表示
	private int[][] graph=new int[n][n];
	//数字的组合
	private String combination="";
	public Set<String> getAllCombination(){
		//构造图
		buildGraph();
		//用来存放所有集合
		Set<String> set=new HashSet<String>();
		//分别从不同的结点出发深度遍历图
		for(int i=0;i<n;i++){
			this.depthFirstSearch(i,set);
		}
		return set;
	}
	private void buildGraph(){
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				if(i==j){
					graph[i][j]=0;
				}else{
					graph[i][j]=1;
				}
			}
		}
		//确保在遍历3与5是不可达的
		graph[3][5]=0;
		graph[5][3]=0;
	}
	//对树从结点start位置开始进行深度遍历
	private void depthFirstSearch(int start,Set<String> set){
		visited[start]=true;
		combination=combination+numbers[start];
		if(combination.length()==n){
			//4不出现在第三个位置
			if(combination.indexOf("4")!=2){
				set.add(combination);
			}
		}
		for(int j=0;j<n;j++){
			if(graph[start][j]==1 && visited[j]==false){//表示start结点与j结点有连线,且没被访问过
				depthFirstSearch(j, set);
			}
		}
		combination=combination.substring(0,combination.length()-1);
		visited[start]=false;
	}
	
}
运行结果为:

312254
321524
325412
212543
125234
152324
123245
123254
251423
322145
431225
523241
312245
421325
212345
325421
315242
232145
125243
132524
341225
432251
322154
232154
132254
142325
431252
345221
413225
522134
451322
215243
512324
512423
213245
232451
321254
345212
231452
341252
512432
243152
213254
342251
321245
243215
223415
241523
342512
123425
342215
152423
425231
251324
432215
245123
422513
225143
243125
342521
252314
322415
422315
342125
432512
215234
245132
322514
225134
221345
345122
231425
152342
225431
152243
321542
412523
521234
123452
251342
521324
432521
242513
322541
342152
431522
521342
152234
432125
521243
152432
543122
225413
223451
243251
251432
125432
122345
122543
543221
425123
252341
143252
252413
512243
252143
245213
451232
542213
132452
325241
513242
125423
231245
521423
245231
542231
421523
543212
425132
321425
231542
521432
412325
452231
522413
231254
522314
425213
215432
145223
252431
143225
223145
145232
322451
232514
423251
541232
312452
321452
215423
252134
512234
223154
451223
231524
541223
522431
213452
325142
542321
241325
512342
423215
542312
542123
423125
522341
523124
413252
312425
522143
542132
452213
312524
132425
452312
312542
142523
325124
452123
251243
432152
513224
452132
232415
415223
213425
452321
523421
132245
523142
315422
541322
523214
341522
242315
221543
232541
325214
251234
132542
423152
415232
315224
523412
513422


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值