1.代码实现
package main.java.ClassicalAlgorithm;
import java.util.*;
/**
* @auther 1taoliu
* @date 2021/3/8 上午10:48
*/
public class Permutation {
public static List<List<Integer>> list = new ArrayList<>();
public static void main(String[] args) {
fullPerm(new int[] {1,2,3,4},new Stack<Integer>());
//cPerm(new int[]{1,2,3,4,5},5,3,new Stack<Integer>());
for (List<Integer> list1:list){
System.out.println(list1);
}
}
/**
* 全排列
*
* @param array 数组
* @param stack 排列结果
*/
public static void fullPerm(int[] array, Stack<Integer> stack) {
//递归出口
if (array.length <= 0) {
//添加结果
List<Integer> listTemp = new ArrayList<>();
for (int i : stack) {
listTemp.add(i);
}
list.add(listTemp);
} else {
for (int i = 0; i < array.length; i++) {
int[] temp = new int[array.length - 1];
//将索引为i左侧的数据添加进数组
System.arraycopy(array, 0, temp, 0, i);
//将索引为i右侧的数据添加进数组
System.arraycopy(array, i + 1, temp, i, array.length - i - 1);
//将索引为i的数据添加进结果
stack.push(array[i]);
//递归调用
fullPerm(temp, stack);
//移除上一次添加进去的数据
stack.pop();
}
}
}
/**
* @param array 待排列数据
* @param n n个数
* @param m m个数
* @param stack 选取的m-1个数据
*/
public static void cPerm(int[] array,int n,int m,Stack<Integer> stack){
if (m==1){
for (int i:array){
List<Integer> listTemp = new ArrayList<>();
for (int j:stack){
listTemp.add(j);
}
listTemp.add(i);
list.add(listTemp);
}
}
for (int i = 0; i < n; i++) {
stack.push(array[i]);
int[] temp = new int[array.length - 1];
//将索引为i左侧的数据添加进数组
System.arraycopy(array, 0, temp, 0, i);
//将索引为i右侧的数据添加进数组
System.arraycopy(array, i + 1, temp, i, array.length - i - 1);
//递归调用
cPerm(temp,n-1,m-1,stack);
stack.pop();
}
}
}
2.核心思想
全排列:每次从数组中选取一个数,并把这个数字移出数组,并递归调用以缩小数组范围,当数组长度为0时,跳出当前递归。
选择排列:n选m,在全排列当基础上进行适当改动,分解问题,如5选3 --> 4选2 --> 3选1,将已有的m-1个数据与剩余的n+1-m分别组合即可获得最终结果。