首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java計算排列組合:需求澄清與標準算法實現

     編輯:程式設計綜合問答

原問題描述模糊(\"0,1,2,3這三個數每行一個數共15行\..."),無法直接給出代碼。本文梳理常見排列組合場景,提供標準Java實現模板,助你根據實際需求選擇。

常見場景澄清

場景描述數學概念輸出示例 (輸入 0,1,2,3)
從4個數中選3個,**有序**排列排列 P(4,3) = 24012, 013, 021, 023, 031, 032, 102, 103...
從4個數中選3個,**無序**組合組合 C(4,3) = 4012, 013, 023, 123
4個數**全排列**P(4,4) = 240123, 0132, 0213, 0231...
允許重複,長度3的**有序排列**4^3 = 64000, 001, 002, 003, 010...
生成15行,每行從0-3隨機取一個數隨機採樣0, 3, 1, 2, 0, 1, 3, 2, 3, 0, 1, 2, 3, 1, 0

通用遞歸模板(可適配上述所有場景)


import java.util.*;

public class Combinatorics {
    // 核心遞歸:從 candidates 選擇,構建 path,滿足條件加入 result
    public static void backtrack(List candidates, List path, 
                                 List> result, 
                                 boolean[] used, // 用於不重複選擇
                                 int targetLength, boolean allowRepeat) {
        if (path.size() == targetLength) {
            result.add(new ArrayList<>(path));
            return;
        }
        
        for (int i = 0; i < candidates.size(); i++) {
            if (used[i]) continue; // 不允許重複時跳過已用
            
            // 剪枝邏輯可在這裡添加(如去重、順序限制)
            
            used[i] = true;
            path.add(candidates.get(i));
            
            backtrack(candidates, path, result, used, targetLength, allowRepeat);
            
            path.remove(path.size() - 1);
            used[i] = false;
            
            // 允許重複時,不標記 used,但需控制遞歸深度防無限循環
            if (allowRepeat) {
                // 需額外邏輯控制,如按索引非遞減保證無序組合不重複
            }
        }
    }

    // 便捷入口
    public static List> permute(int[] nums, int k) { // 排列 P(n,k)
        List> res = new ArrayList<>();
        backtrack(Arrays.stream(nums).boxed().toList(), new ArrayList<>(), res, 
                  new boolean[nums.length], k, false);
        return res;
    }
    
    public static List> combine(int[] nums, int k) { // 組合 C(n,k)
        List> res = new ArrayList<>();
        // 組合需保證索引遞增避免重複
        combineHelper(nums, 0, k, new ArrayList<>(), res);
        return res;
    }
    
    private static void combineHelper(int[] nums, int start, int k, 
                                      List path, List> res) {
        if (path.size() == k) { res.add(new ArrayList<>(path)); return; }
        for (int i = start; i < nums.length; i++) {
            path.add(nums[i]);
            combineHelper(nums, i + 1, k, path, res);
            path.remove(path.size() - 1);
        }
    }
}

Java 8+ Stream 一行式(簡單場景)


// 全排列 (借用第三方庫或自寫工具)
// 隨機採樣 15 行
new Random().ints(15, 0, 4).forEach(System.out::println); // 0-3隨機數

// 笛卡爾積 (允許重複排列)
List cartesian = Stream.of(new int[]{0,1,2,3}, new int[]{0,1,2,3}, new int[]{0,1,2,3})
    .reduce(Stream.of(new int[0]), 
            (a, b) -> a.flatMap(x -> Arrays.stream(b).map(y -> concat(x, y))),
            (a, b) -> a)
    .collect(Collectors.toList());

提問建議:描述清晰得準確答案

  1. 輸入集合:確切元素、是否可重複。
  2. 輸出長度/結構:固定長度?變長?單值?序列?
  3. 順序敏感度:`[0,1]` 和 `[1,0]` 算同一種嗎?
  4. 約束條件:和為定值?包含特定元素?無相鄰重複?
  5. 數量預期:具體數字(如15行)還是「所有可能」?
算法無萬能鑰,精確定義問題模型是解題第一步。補全上述信息,任意語言皆可實現。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved