1. 程式人生 > >遞歸控制-列出所有組合

遞歸控制-列出所有組合

info list() str image 測試 入參 void 結果 tin

0.目錄

1.遞歸思路

2.Java代碼實現

  • 2.1 分開考慮初始值
  • 2.2 合並各自初始條件
  • 2.3 維護side-effect
  • 2.4 測試用例

1.遞歸思路

列出所有組合,例如從1,2,3,4中任取2個元素,求出所有的組合。

面對combinations([1,2,3,4], 2):
遞歸思路為:

  • 選1 → combinations([2,3,4], 1)
  • 不選1 → combinations([2,3,4], 2)

    2.Java代碼實現

    2.1 分開考慮初始值

    先分開考慮傳入參數的初始值
    /**
     * Generates all combinations and output them,
     * selecting n elements from data
     */
    public void combinations(List<Integer> data, int n) {
        // initial value for recursion
        if (data.isEmpty()) {
            if (n == 0) {
                // output empty list
            }
            return;
        }

        if (n < 0) {
            return;
        }

        if (n == 0) {
            // output empty list
            return;
        }

        // select element 0
        combinations(data.subList(1, data.size()), n - 1);

        // un-select element 0
        combinations(data.subList(1, data.size()), n);
    }

2.2 合並各自初始條件

合並初始值條件後,考慮兩個問題:
如何選擇元素?如何輸出?

    /**
     * Generates all combinations and output them,
     * selecting n elements from data
     */
    public void combinations(List<Integer> data, int n) {
        // how to select elements
        // how to output

        if (n == 0) {
            // output all selected elements
            return;
        }

        if (data.isEmpty()) {
            // output empty list
            return;
        }

        // select element 0
        combinations(data.subList(1, data.size()), n - 1);

        // un-select element 0
        combinations(data.subList(1, data.size()), n);
    }

2.3 維護side-effect

維護一個selected,也就是之前所選擇的的所有元素。

    /**
     * Generates all combinations and output them,
     * selecting n elements from data
     */
    public void combinations(
        List<Integer> selected, List<Integer> data, int n) {
        if (n == 0) {
            // output all selected elements
            for (Integer i : selected) {
                System.out.print(i);
                System.out.print(" ");
            }
            System.out.println();
            return;
        }

        if (data.isEmpty()) {
            // output empty list
            return;
        }

        // select element 0
        selected.add(data.get(0));
        combinations(selected, data.subList(1, data.size()), n - 1);

        // un-select element 0
        selected.remove(selected.size() - 1);
        combinations(selected, data.subList(1, data.size()), n);
    }

2.4 測試用例

測試程序是否正確運行:

    public static void main(String[] args) {
        Combinations comb = new Combinations();
        comb.combinations(
            new ArrayList<>(), Arrays.asList(1, 2, 3, 4), 2);
    }

運行結果為
技術分享圖片
多測幾個極端用例

    public static void main(String[] args) {
        Combinations comb = new Combinations();
        comb.combinations(
            new ArrayList<>(), Arrays.asList(1, 2, 3, 4), 2);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(), 2);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(), 0);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(1, 2, 3, 4), 1);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(1, 2, 3, 4), 0);
        System.out.println("=================");
    }

運行結果為
技術分享圖片

全部代碼:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Combinations {

    /**
     * Generates all combinations and output them,
     * selecting n elements from data
     */
    public void combinations(
        List<Integer> selected, List<Integer> data, int n) {
        if (n == 0) {
            // output all selected elements
            for (Integer i : selected) {
                System.out.print(i);
                System.out.print(" ");
            }
            System.out.println();
            return;
        }

        if (data.isEmpty()) {
            // output empty list
            return;
        }

        // select element 0
        selected.add(data.get(0));
        combinations(selected, data.subList(1, data.size()), n - 1);

        // un-select element 0
        selected.remove(selected.size() - 1);
        combinations(selected, data.subList(1, data.size()), n);
    }

    public static void main(String[] args) {
        Combinations comb = new Combinations();
        comb.combinations(
            new ArrayList<>(), Arrays.asList(1, 2, 3, 4), 2);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(), 2);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(), 0);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(1, 2, 3, 4), 1);
        System.out.println("=================");
        comb.combinations(
            new ArrayList<>(), Arrays.asList(1, 2, 3, 4), 0);
        System.out.println("=================");
    }
}

遞歸控制-列出所有組合