/** * 對傳入的basecodes取sub位元素作組合. * * @param basecodes:該集合的單元爲組合基數的單元元素 * @param sub:須要對基數作多少位的組合 * @return */ public static List<Set<String>> produceAllPrecode(List<String> basecodes, int sub) { List<Set<String>> result = new ArrayList<>(); Set<String> single = new HashSet<>(); int size = basecodes.size(); if (size < sub) { return result; } // 總組數:C(size,sub) int total = cnm(size, sub); while (true) { if (result.size() >= total) { break; } single.add(basecodes.get(getRandom(size))); if (single.size() == sub) { if (!result.contains(single)) { Set<String> temp = new HashSet<>(); temp.addAll(single); result.add(temp); } single.removeAll(single); continue; } } return result; } // 遞歸算法計算階乘:n! public static int factorials(int n) { return (n > 1) ? n * factorials(n - 1) : 1; } // 計算排列值:A(n,m),從給定n個數的元素中取出指定m個數的元素,進行排序 public static int anm(int n, int m) { return factorials(n) / factorials(n - m); } // 計算組合值:C(n,m),從給定n個數的元素中僅僅取出指定m個數的元素,不考慮排序 public static int cnm(int n, int m) { return anm(n, m) / factorials(m); } /** * 生成0~max之間的隨機數。包含0,不包含max */ public static int getRandom(int max) { return new Random().nextInt(max); }
測試代碼java
// 組合測試 @Test public void test04() { String[] codeArr = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // String[] codeArr = { "a", "b", "c", "d", "e"}; List<String> basecodes = Arrays.asList(codeArr); int sub = 5; List<Set<String>> precodes = CqsscUtil.produceAllPrecode(basecodes, sub); List<String> sort = new ArrayList<>(); for (Set<String> precode : precodes) { sort.add(precode.toString()); } Collections.sort(sort); System.out.println("總組數:" + CqsscUtil.cnm(basecodes.size(), sub)); for (String code : sort) { System.out.println(code); } }