数字全排列递归算法

程序的主要思路是:

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

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

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

    可见这是一个递归的过程,把对整个序列做全排列的问题归结为对它的子序列做全排列的问题,注意我没有描述Base Case怎么处理,你需要自己想。你的程序要具有通用性,如果改变了N和数组a的定义(比如改成4个数的数组),其它代码不需要修改就可以做4个数的全排列(共24种排列)。

    解题过程:

   (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 = 4,5,6,……的时候,以此类推。


例题:用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、412345等,
要求:"4"不能在第三位,"3"与"5"不能相连

/*题目如下:用1、2、2、3、4、5这六个数字,用java写一个main函数,打印出所有不同的排列,如:512234、4123

可以先简单求出总数,以便验证

1,2,2,3,4,5全排列:(乘以二是两种情况,除以二是2重复的个数减半)

1、A(6,6)/2全排列,一半是2重复的

2、2*C(5,1)*A(4,4)/2  排列包含35和包含53的情况,将35和53看做一个整体,则有五个位置可以选,剩下四个任意排,除去2重复的情况,其实也可以是2*A(5,5)/2 将35或53看做一个整体任排,除去2重复的一半

3、A(5,5)/2 数字4在第三位时其他5个任意排,除去2重复的情况

4、第二种情况其实跟第三种情况有交集,即4在第三位的时候也包含了35和53在一起的一部分这部分个数为2*C(3,1)*A(3,3)/2 数字4在第三位只有三个位置可以放下35和53的组合,剩下的三个全排列除掉2重复的部分

最终结果是

   A(6,6)/2 - 2*C(5,1)*A(4,4)/2 - A(5,5)/2 + 2*C(3,1)*A(3,3)/2

=360 - 120 - 60 + 18

=198                     

 

 

代码
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;


public class arrange {
    public static int count = 0;
    public static Set<String> all  = new TreeSet();
    public static void swap(char [] arr, int x, int y) {
        if (x == y || arr[x] == arr[y]) {
            return;
        }
        char tmp = arr[x];
        arr[x] = arr[y];
        arr[y] = tmp;
    }
    
    public static void arrange(char [] arr, int begin, int end) {
        if (begin == end) {
            String str = "";
            if (arr[2] != '4') {//过滤4在第三位的元素
                for (int i = 0; i < arr.length; i++) {
                    str += arr[i];
                }//去除包含35,53的元素
                if (!str.contains("35") && !str.contains("53") ) {
                   // System.out.println(++count + ":" +str);
                   all.add(str); //利用集合消除重复元素
                }
            }
        }else {
            for (int i = begin; i <= end; i++) {
                swap(arr, begin, i);
                arrange(arr, begin + 1, end);
                swap(arr, begin, i);
            }
        }
    }
    
    public static void print() {
        Iterator<String> it = all.iterator();
        System.out.println(all.size());
        int count = 0;
        while (it.hasNext()) {
            String string = (String) it.next();
            System.out.print(string + "  ");
            if (++count % 9 == 0) {
                System.out.println();
            }
        }
        System.out.print(all.size());
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub

        char []arr = new char[] {'1','2','2','3','4','5'};
        arrange(arr, 0, arr.length - 1);
        print();
    }
    
}


你可能感兴趣的:(数字全排列递归算法)