回溯算法 - 全排列


(1)問題描述:對於給定的集合 A{a1,a2,...,an},其中的 n 個元素互不相同,如何輸出這 n 個元素的所有排列(全排列),時間復雜度為O(2n);

  例如:{a, b, c}

  全排列:{a, b, c}, {a, c, b}, {b, a, c}, {b, c, a}, {c, a, b}, {c, b, a}

(2)回溯算法思想:

  這里以 A{a, b, c} 為例,來說明全排列的生成方法,對於這個集合,其包含 3 個元素,所有的排列情況有 3!=6 種,對於每一種排列,其第一個元素有 3 種選擇 a, b, c,對於第一個元素為 a的排列,其第二個元素有 2 種選擇 b, c;第一個元素為 b 的排列,第二個元素也有2種選擇a,c,……,依次類推,我們可以將集合的全排列與一棵多叉樹對應。如下圖所示:

  

(3)算法代碼:

public class FullPermutation {

    /**
     * 存放數據數組
     */
    private static Integer[] data;

    /**
     * 數據數量
     */
    private static Integer num;

    /**
     * 交換數據
     */
    public static void swap(int x, int y) {
        Integer temp = data[x];
        data[x] = data[y];
        data[y] = temp;
    }

    /**
     * 初始化數據
     */
    private static void initData() {
        Scanner input = new Scanner(System.in);
        System.out.println("請輸入數據數量:");
        num = input.nextInt();
        System.out.println("請輸入數組數據");
        data = new Integer[num];
        for (int i = 0; i < data.length; i++) {
            data[i] = input.nextInt();
        }
    }

    /**
     * 遞歸回溯排列樹求解
     */
    private static void backtrack(int t) {
        if (t == data.length) {
            System.out.print("排列樹為: ");
            Stream.of(data).forEach(element -> System.out.print(element + " "));
            System.out.println();
        }
        for (int i = t; i < data.length; i++) {
            swap(t, i);
            backtrack(t + 1);
            swap(t, i);
        }

    }


    public static void main(String[] args) {
        // 初始化數據
        initData();

        // 遞歸回溯排列樹求解
        backtrack(0);
    }

}

(4)輸入輸出

請輸入數據數量:
4
請輸入數組數據
1 2 3 4
排列數為: 1 1 2 3 
排列數為: 1 1 3 2 
排列數為: 1 2 1 3 
排列數為: 1 2 3 1 
排列數為: 1 3 2 1 
排列數為: 1 3 1 2 
排列數為: 1 1 2 3 
排列數為: 1 1 3 2 
排列數為: 1 2 1 3 
排列數為: 1 2 3 1 
排列數為: 1 3 2 1 
排列數為: 1 3 1 2 
排列數為: 2 1 1 3 
排列數為: 2 1 3 1 
排列數為: 2 1 1 3 
排列數為: 2 1 3 1 
排列數為: 2 3 1 1 
排列數為: 2 3 1 1 
排列數為: 3 1 2 1 
排列數為: 3 1 1 2 
排列數為: 3 2 1 1 
排列數為: 3 2 1 1 
排列數為: 3 1 2 1 
排列數為: 3 1 1 2 

(5)總結:回溯算法是有一定的規律可循的,根據問題,找出解空間的組織結構,選擇恰當的解決方案:回溯算法模板

  回溯算法一般采用深度優先的方式,遞歸求解,人的思維一般對遞歸求解的問題有一定的想象難度,建議在紙上根據代碼的流程,畫一畫走一遍詳細的過程,便於理解回溯算法的核心要點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM