排列算法
问题描述:给定s个数X={r1,r2,r3…rs}对其进行全排列。通过递归的方法解决。
问题分析:对于这个问题我们用Perm(X)表示X的全排列,对这s个数排列其实就是对n个位置都做一个选择,每一个位置确定一个数,而我们应该知道的就是,一个数放在一个位置上的时候,这个数就不能再放在另外的位置上,所以我们从左向右进行排列,假定n是在数组中的起点,m为在数组中的终点,从第一个位置,我们可以知道一共有m-n+1个可能,也就是从n到m的所有数(这里就有一个循环),当第一个数确定下来,就还有m-n个数,这m-n个数进行和刚才一样的操作,也就是另一个全排列,这就是和上面完全一样的问题,只是问题规模变小了一点,那么什么时候结束呢,当然就是当所有位置都被确定的时候程序停止,输出一次排列结果。
递归:首先我们应该明白使用递归最重要的就是递归式,而递归式中很重要的就是终止条件,如果没有终止条件程序将永远运行下去无法停止,而本问题的终止条件就是n==m,其中n代表排列的起点,起点逐渐靠近终点,当起点和终点重合时代表所有的位置都已经被确定了。
所以(1)当n=m时,一次排列完成输出排列结果
(2)当n<m时,对第n个位置进行选择占位,并继续n+1到m的排列。
(3)理论上来讲n不可能大于m,除非输入错误。
import java.util.Scanner;
//这个算法是递归求解全排列问题
public class Perm {
public static void main(String[] args) {
int[] numbers=new int[5];
for(int i=0;i<numbers.length;i++) {
numbers[i]=i;
}
Scanner scanner=new Scanner(System.in);
System.out.println("请输入n,取值范围[0,5]");
int n=scanner.nextInt();
System.out.println("请输入m,取值范围[n,5]");
int m=scanner.nextInt();
doPerm(numbers,n,m);
}
private static void doPerm(int[] numbers,int n,int m) {
if(n==m) {
for(int i=0;i<m;i++) {
System.out.print(numbers[i]);
}
System.out.println();
}else {
for(int i=n;i<m;i++) {
swap(numbers,i,n);
doPerm(numbers,n+1,m);
swap(numbers,i,n);
}
}
}
private static void swap(int[] numbers,int k,int m) {
int temp;
temp=numbers[k];
numbers[k]=numbers[m];
numbers[m]=temp;
}
}
swap()方法是对数组中的两个位置的数进行交换,一次排列完成后还需要还原成最初的样子,进行第二次排列。如有错误欢迎指出