之前在想关于计算行列式的问题的时候,突然遇到了了这个问题:给定一个数据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);
}
}
}