首先,M選N的算法規則:要從長度爲M的數組中選N個數,列出全部組合:java
例子:求5中選3的組合,用數學公式計算組合爲C5-3=(5x4x3)/(3x2x1)=10,算法窮舉法驗證:算法
1 2 3 4 5(原始數組)
1 1 1 0 0 -->1,2,3
1 1 0 1 0 -->1,2,4
1 0 1 1 0 -->1,3,4
0 1 1 1 0 -->2,3,4
1 1 0 0 1 -->1,2,5
1 0 1 0 1 -->1,3,5
0 1 1 0 1 -->2,3,5
1 0 0 1 1 -->1,4,5
0 1 0 1 1 -->2,4,5
0 0 1 1 1 -->3,4,5數組
下面用代碼實現:優化
/** * M選N算法 */ public static List m2n(List source, int n) { List list = Lists.newArrayList(); // 初始化新數組,長度和原數組一致,而且前n爲填充1,其他爲0 int size = source.size(); Integer[] zero = new Integer[size]; for (int i = 0; i < size; i++) { if (i < n) { zero[i] = 1; } else { zero[i] = 0; } } // 尋找【10】,交換,移動 for (; ; ) { // 新數組的1的下標對應原數組的下標,生成結果集 List sublist = Lists.newArrayList(); for (int i = 0; i < size; i++) { if (zero[i].equals(1)) { sublist.add(source.get(i)); } } list.add(sublist); // 尋找【10】組合,交換爲【01】,若是沒找到,則表明已結束 int i = Joiner.on("").join(zero).indexOf("10"); if (i == -1) { break; } zero[i] = 0; zero[i + 1] = 1; // 統計交換後的01位置以前有多少個1,並將其移動到最左端 long count = Arrays.asList(zero).subList(0, i).stream().filter(o -> o.equals(1)).count(); for (int j = 0; j < i; j++) { if (j < count) { zero[j] = 1; } else { zero[j] = 0; } } } return list; }
歡迎留言指出能夠優化更簡的地方,謝謝。code