之前遇到实现全排列这个问题,也是思考了好久,现在将学习的过程做一简单小结:
一、无重复元素全排列
无重复元素全排列即需要全排列的元素中没有重复的,这种情况使用递归算是比较简单一点,在这里主要以整数数组{1,2,3,4}为例,做一简单分析,如果需要对其他元素进行全排列,只需将里面的元素进行替换即可。
使用递归进行实现全排列,主要的思想就是逐个固定,让后面的元素依次交换位置,最后实现全排列:
1、一个数的全排列:只有本身这一种情况。
2、两个数的全排列:如排列{1,2};
第一步:将元素1放在位置0并固定,剩下的部分{2}进行全排列(与情况1一致,可使用上一步操作),即{1,2};
第二步:将元素2放在位置0并固定,剩下的部分{1}进行全排列(与情况1一致,可使用上一步操作),即{2,1}。
3、三个数的全排列:如排列{1,2,3};
第一步:将元素1放在位置0并固定,剩下的部分{2,3}进行全排列(与情况2一致,可使用上一步操作),即{1,2,3}和{1,3,2};
第二步:将元素2放在位置0并固定,剩下的部分{1,3}进行全排列(与情况2一致,可使用上一步操作),即{2,1,3}和{2,3,1};
第三步:将元素3放在位置0并固定,剩下的部分{1,2}进行全排列(与情况2一致,可使用上一步操作),即{3,1,2}和{3,2,1}。
看到这里,基本应该很清楚了,也能总结m个元素的规律:
4、m个数全排列:就是将m个数依次放在第0个位置并固定,剩下的部分再次进行全排列,依次递归,最后,一个数的全排列作为递归的出口。
public class Main {
private static void permutation(int[] arr , int n) {
int length = arr.length;
if(n>=length-1) {//当n定位到最后一个数时,即到递归出口
for(int i:arr) {
System.out.print(i);
}
System.out.println();
}else {
for(int i=n;i<length;i++) {
{int temp = arr[n]; arr[n] = arr[i]; arr[i] = temp;}
permutation(arr,n+1);//对剩下的length-n-1个数全排列
{int temp = arr[n]; arr[n] = arr[i]; arr[i] = temp;}
}
}
}
public static void main(String[] args) {
int[] arr = {1,2,3,4};
permutation(arr,0);
}
}
运行结果为:
1234
1243
1324
1342
1432
1423
2134
2143
2314
2341
2431
2413
3214
3241
3124
3142
3412
3421
4231
4213
4321
4312
4132
4123
Process finished with exit code 0
二、有重复元素全排列
有重复元素的全排列,比如{1,2,2,1}这种类型的全排列,基本思路与上述无重复全排列基本一致,但是如果按照第一种的思路会导致大量的重复组合,因此,每次只需在把某个元素放在位置0的时候,判断是否重复即可,具体代码如下:
import java.util.ArrayList;
import java.util.List;
public class Main {
private static void permutation2(int arr[] , int n) {
int length = arr.length;
List<Integer> exis = new ArrayList<Integer>();//存放第零个位置已经有过的数字
if(n>=length-1) {
for(int i:arr) {System.out.print(i);}
System.out.println();
}else {
for(int i=n;i<length;i++) {
if(!exis.contains(arr[i])) { //如果arr[i]不在exis中,则可以把arr[i]放在第零个位置
exis.add(arr[i]);//将arr[i]放进exis
{int temp = arr[n]; arr[n] = arr[i]; arr[i] = temp;}
permutation2(arr,n+1);
{int temp = arr[n]; arr[n] = arr[i]; arr[i] = temp;}
}
}
}
}
public static void main(String[] args) {
int[] arr = {1,2,2,1};
permutation2(arr,0);
}
}
运行结果如下所示:
1221
1212
1122
2121
2112
2211
在实现全排列的同时,避免了重复。