Java递归求全排列详解

Java递归求全排列详解


推荐博客:
博客园Java全排列递归算法,结尾的解释很形象了
csdn的大佬写的,和我下面的代码思路基本一致

全排列的递归思想解释:

全排列的数学定义就不再过多解释,考虑递归算法的实现可从下面几点入手(以数组为例,如对其他元素排列,将元素编号放入数组即可):

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时为递归>的出口。

代码

注意点

  • 一个数的全排列就是其本身

程序的主要思路是:参考文章

把第1个数换到最前面来(本来就在最前面),准备打印1xx,再对后两个数23做全排列。

把第2个数换到最前面来,准备打印2xx,再对后两个数13做全排列。

把第3个数换到最前面来,准备打印3xx,再对后两个数12做全排列。

可见这是一个递归的过程,把对整个序列做全排列的问题归结为对它的子序列做全排列的问题

    解题过程:

   (1) 当 N = 1的时候,则直接打印数列即可。

   (2) 当 N = 2的时候,设数组为 [a, b]

            打印a[0], a[1] (即a,b)

            交换a[0],a[1]里面的内容

            打印a[0],a[1]   (此时已变成了 [b, a](3) 当 N = 3的时候,数组为 [a, b, c]

 把a放在 a[0] 的位置(原本也是如此,a[0] = a[0]),打印b,c的全排列(即a[1], a[2]的全排列)
                       a  b  c

                       a  c  b

 把b放在a[0]的位置(这时候需要交换原数组的a[0]和a[1]),然后打印a, c的全排列
                       b   a  c

                       b   c  a                       

 打印完后再换回原来的位置,即a还是恢复到a[0],b还恢复到a[1]的位置

 把c放在a[0]的位置(这时候需要交换的是原数组的a[0]和a[2]),然后打印a, b的全排列
             c  b  a
             c  a  b
 打印完后再换回原来的位置,即a还是恢复到a[0],b还恢复到a[1]的位置,至此,全排列完成
 当 N = 456,……的时候,以此类推。
	//全排列函数(递归),参数k是确定第k个位上的字符
	//k是数组元素下标,从0开始,所以递归终止条件中arr.length可以不减1,结果一样的
	private static void f(char[] arr, int k) {
    
    
		if (k == arr.length-1) {
    
    
			System.out.println(arr);
		}
		
		for (int i = k; i < arr.length; i++) {
    
    
			//交换位置
			char t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
			
			f(arr, k+1);
			
			//回溯
			t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
		}
	}

无重复元素测试

public class Test{
    
    

	public static void main(String[] args) {
    
    
		char[] cArr={
    
    'A','B','C'};
		f(cArr,0);
		
	}

	//全排列函数(递归),参数k是确定第k个位上的字符
	//k是数组元素下标,从0开始,所以递归终止条件中arr.length可以不减1,结果一样的
	private static void f(char[] arr, int k) {
    
    
		if (k == arr.length-1) {
    
    
			System.out.println(arr);
		}
		
		
		for (int i = k; i < arr.length; i++) {
    
    
			char t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
			
			f(arr, k+1);
			
			//回溯
			t = arr[k];
			arr[k] = arr[i];
			arr[i] = t;
		}
	}
}

运行结果

在这里插入图片描述

有重复元素测试结果

使用AAB测试,结果有重复项
在这里插入图片描述

如何去重?

可以在全局new一个set(注意使用static),然后每次把全排列的结果add到set里就可以了
详见博客https://yinglongwu.blog.csdn.net/article/details/108833986

猜你喜欢

转载自blog.csdn.net/qq_43594119/article/details/108943855