(算法)全排列的递归算法Java实现过程
一、无重复项的全排列
全排列的数学定义就不再过多解释,考虑递归算法的实现可从下面几点入手(以数组为例,如对其他元素排列,将元素编号放入数组即可):
1、一个数的全排列,如排列{1},就是这个数本身这一种情况
2、两个数的全排列,如排列{1,2}:
第一步:将{1}放在第零个位置,剩下的{2}进行一个数的全排列,结果为{1,2}
第二步:将{2}放在第零个位置,剩下的{1}进行一个数的全排列,结果为{2,1}
即两个数的全排列为以上2种情况。
3、三个数的全排列,如排列{1,2,3}:
第一步:将{1}放在第零个位置,剩下的{2,3}进行两个数的全排列,结果为{1,2,3} {1,3,2}
第二步:将{2}放在第零个位置,剩下的{1,3}进行两个数的全排列,结果为{2,1,3} {2,3,1}
第三步:将{3}放在第零个位置,剩下的{1,2}进行两个数的全排列,结果为{3,1,2} {3,2,1}
即三个数的全排列为以上6种情况。
4、即m个数(无重)的全排列,就是将m个数分别放在第零个位置,再将剩下的m-1个数的全排列加在后面,当m-1=1时为递归的出口。
例题:
代码实习:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;
public class Main2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
char buf[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
Set<String> lists = new TreeSet<>();
perm(buf, 0, buf.length - 1, lists, n);
}
public static void perm(char[] buf, int start, int end, Set<String> lists, int a) {
if (start == end) {// 当只要求对数组中一个字母进行全排列时,只要就按该数组输出即可(特殊情况)
StringBuilder strs = new StringBuilder("");
for (int i = 0; i < buf.length; i++) {
strs.append(buf[i]);
}
lists.add(strs.toString());
if (lists.size() == a) {
Object[] arr = lists.toArray();
System.out.println(arr[arr.length - 1]);
return ;
}
} else {// 多个字母全排列(普遍情况)
ff: for (int i = start; i <= end; i++) {// (让指针start分别指向每一个数)
char temp = buf[start];// 交换数组第一个元素与后续的元素
buf[start] = buf[i];
buf[i] = temp;
perm(buf, start + 1, end, lists, a);// 后续元素递归全排列
temp = buf[start];// 将交换后的数组还原
buf[start] = buf[i];
buf[i] = temp;
}
}
}
}
分析:
超时,但是不会优化,希望以后会回来优化!
令start分别等于0,1,2,3....end并且多次调用perm方法形成多个循环,最外层镶嵌内层,内层再镶嵌内层。想不明白的时候可以按照图模拟一下(a,b,c,d)的全排列。
第二种做法:
12345找出这个序列全排列的第16个
计算方法就是如果你要求12345全排列的第16个的话
求第一位 用15/4!=0, 余15,那么前面有0个数,得到1。那么此时12345剩下了2345。
求第二位 用余的15/3! = 2, 余3,那么前面有2个数,得到4。剩下235。
求第三位 用余的3/2! = 1, 余1,那么前面有1个数,得到3,剩下25。
求第四位 用余的1/1! = 1, 余0,那么前面有1个数,得到5,剩下2。
求第五位 即2。
代码实现:
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
List<Integer>lists = new ArrayList<>();
int[]arr = {0,1,2,3,4,5,6,7,8,9};
int h = 0;
int a = sc.nextInt();
int n = a-1;
int k = 9;
for (int i = 0; i < arr.length; i++) {
h=n/jie(k);
n=n%jie(k);
for (int j = 0; j < arr.length; j++) {
if(h==0&!lists.contains(arr[j])) {
lists.add(arr[j]);
break;
}else if(!lists.contains(arr[j])) {
h--;
}
}
k--;
}
Object[]arrs = lists.toArray();
for (int i = 0; i < arrs.length; i++) {
System.out.print(arrs[i]);
}
}
public static int jie(int k ) {
int sum = 1;
for (int i = 1; i <=k; i++) {
sum*=i;
}
return sum;
}
}