计算所给字符的排列组合情况

之前在想关于计算行列式的问题的时候,突然遇到了了这个问题:给定一个数据m,输出1,2,3,…..m这些数排列组合的所有情况,例如给定2,则输出:12,21,;给定3,则输出123,132,213,231,312,321。

对于这个问题,我想到了两个思路:

①.利用循环,找出从pow(10,m-1)到m*pow(10,m-1)中找出符合两个条件的数:一.所有计数单位的数均小于m;二.所有计数单位上的数均不一样。这是最开始的思路,最后也把行列式计算问题解决了,但是用这种方法有一个问题,那就是循环的次数太多了,对于一些比较大的数这个方法就不是很适用了。

②.这个思路是今天想出来的:其实也是一个简单的数学原理问题:

当m=1时:

输出:1

当m=2时:

输出:12 21

当m=3时:

输出:123   132   321   213   231   321

经过上的例子可以发现以下的规律:

一.m个数,具有m!种排列组合情况;

二. 下一次排列是在上一次排列的基础上实现的,例如,m=3就是在m=2的基础上,在所有可能情况的位置上添上3;

三.这一点其实是第二点延伸,假使把输出结果储存在数组中的话,那么添加的位置将是小于m的所有位置,例如,当m=3时,是在m=2的所有可能性情况的0,1,2上添上3这个数的;

相比于思路①,思路②有两个明显的好处:

一.用时更短,以m=3为例,思路①进行循环的次数为:299(不计算细节),思路②进行的循环数为:59(计算细节)

二.更加符合人的思维,同时也与数学原理相符合。

延伸:

其实,当我们会排所给数的排列组合可能之后,其实也就会了所有这类的排列组合。比如,给定你m符号,要求排除这m个符号可能的排列组合情况。实际上你其实就是对m个数进行排列组合,只不过要对数据进行一下处理;

处理过程:将这些符号储存在数组中,输出时以排列组合的结果为下标即可。

源代码:

import java.util.Scanner;

public class  LineNumbers
{
	//改方法用于计算m的阶乘,m用于控制循环
	public static int computerControl(int m){
		int result=1;
		for(int i=1;i<=m;i++){
			result=result*i;
		}
		return result;
	}
	//计算排列组合的方法
	static void numberLineCaculateWay(int number){
			//numLength表示输入的number具有的排列组合情况数
			int numLength=computerControl(number);
			//num1表示的number-1的情况,num2表示的是number的情况,由于number的情况需要number-1的情况来计算,所以需要两个数组来储存
			//第一个下标表示第几组数据,第二个下标从0开始储存具体的储存内容
			int[][] num1=new int[numLength][number];
			int[][] num2=new int[numLength][number];
			//当number=1的情况:
			num1[0][0]=1;
			num2[0][0]=1;
			//计算的过程从number2开始,结束于number
			//i表示当前添加的数
			for(int i=2;i<=number;i++){
				//t表示:①.已算出结果(储存于num2)的下标,②.表示已算出结果的种类数,最后将等于numLength
				int t=0;
				//j表示的number-1情况下的排列组合情况,运算的结果要基于该数据之上
				for(int j=0;j<computerControl(i-1);j++){
					//k表示添加数据i的下标,前文已解释过,k<=i-1
					for(int k=i-1;k>=0;k--){
						//a表示添加数据的下标
						int a=0;
						//num[e],e<k处理情况,将其直接添加在储存数组num2中
						for(int e=0;e<k;e++){
							num2[t][a]=num1[j][e];
							a++;
						}
						//num[e],e=k处理情况,在k下标处添加i
						num2[t][a]=i;
						a++;
						//num[e],e>k处理情况,将其添加至num2数组中,注意添加的下标
						for(int e=k;e<i-1;e++){
							num2[t][a]=num1[j][e];
						}
						t++;
					}
				}
				//将num2中的数据赋予num1中,因为当i+1时,num1中数据就应该变成(i+1)-1的数据
				for(int j=0;j<computerControl(i);j++){
					for(int k=0;k<number;k++){
						num1[j][k]=num2[j][k];
					}
				}
			}
			//输出结果控制循环
			for(int i=0;i<computerControl(number);i++){
				for(int j=0;j<number;j++){
					System.out.print(num2[i][j]);
				}
				System.out.println();
			}
		}
	public static void main(String[] args) 
	{
		Scanner sc=new Scanner(System.in);
		while(sc.hasNextLine()){
			int number=sc.nextInt();
			numberLineCaculateWay(number);
		}
	}
}

点赞