zoukankan      html  css  js  c++  java
  • 递归实现全排列问题

    描述

    问题是有一组数R,需要输出它的全排列。R的递归可定义如下:
    当个数n为1时,Perm(R) = (r),其中r是集合R中唯一的元素
    当个数n大于1时,Perm(R)由(r1)Perm(R1),(r2)Perm(R2),(r3)Perm(R3),…,(rn)Perm(Rn)构成
    其中Ri = R - {ri} 即该集合中减去对应元素

    思路

    其实说直白点,就是递归地把这组数规模一个一个地缩小,如1,2,3,4. 先把1固定,递归地求2,3,4的全排列,又把2固定,递归地求3,4的全排列……直到只剩一个数,输出这个排列。
    当获取递归数组时,从该组数的第一个,依次和每一位交换(包括本身),得以产生一个新递归数组(如1,2,3,4,先是1和1交换,产生新的2,3,4)
    当1和1交换产生的所有递归完成之后,实际上已经完成了1234,1243,1324,1342,1432,1423的输出,因为1和自己交换之后,产生了2,3,4
    在这个过程中,当1,2,3固定时,只有4剩余,所以输出1,2,3,4.然后固定1,2,交换3,4的位置。输出1,2,4,3.此时1,2固定的已经全部输出,于是返回到只有1固定,那么此时2需要与3交换位置,再进行1,3固定的递归
    其实说这么多,还不如一张图来得实在:
    全排列示意

    代码

    public class Demo {
    	public void Perm(int list[], int k, int m) {
    		if (k == m) {
    			for (int i = 0; i <= m; i++)
    				System.out.print(list[i]);
    			System.out.println();
    		} else {
    			for (int i = k; i <= m; i++) {
    				// 从固定的数后第一个依次交换
    				Swap(list, k, i);
    				Perm(list, k + 1, m);
    				// 这组递归完成之后需要交换回来
    				Swap(list, k, i);
    			}
    		}
    		
    	}
    	public void Swap(int[] list, int i, int j) {
    		int t = list[i];
    		list[i] = list[j];
    		list[j] = t;
    	}
    	public static void main(String[] args) {
    		Demo d = new Demo();
    		int[] arr = {1,2,3,4};
    		d.Perm(arr, 0, 3);
    	}
    }
    
    

    输出

    1234
    1243
    1324
    1342
    1432
    1423
    2134
    2143
    2314
    2341
    2431
    2413
    3214
    3241
    3124
    3142
    3412
    3421
    4231
    4213
    4321
    4312
    4132
    4123

  • 相关阅读:
    JavaScript
    94.Binary Tree Inorder Traversal
    144.Binary Tree Preorder Traversal
    106.Construct Binary Tree from Inorder and Postorder Traversal
    105.Construct Binary Tree from Preorder and Inorder Traversal
    90.Subsets II
    78.Subsets
    83.Merge Sorted Array
    80.Remove Duplicates from Sorted Array II
    79.Word Search
  • 原文地址:https://www.cnblogs.com/zyoung/p/6764371.html
Copyright © 2011-2022 走看看