文/阿敏其人
本文出自“阿敏其人”简书博客,转载请注明出处和链接。
“所谓创意,只是把原有的元素重新组合而已。”美国广告大师詹姆斯。韦伯扬在《创意的生成》一书中如是说。
离开书本,换个角度一看,这个世界也许从来就不存在新的东西,全部就是原有的元素的排列组合罢了。
人类的情感世界太复杂,已知的物理和数学相对靠谱,为了人类整出了 排列数公式 和 组合数公式 。
方便我们排列组合,方便我们研究,方便我们进行“创新”。
排列 和 组合
公式初探
排列数公式:
![](https://img.haomeiwen.com/i1083096/aa2310367670a99d.png)
组合数公式:
![](https://img.haomeiwen.com/i1083096/23dffe384250ae72.png)
排列数公式
从n个不同元素中,任取m(m≤n)个元素(被取出的元素各不相同),按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列。
组合数公式
组合数公式是指从m个不同元素中,任取n(n≤m)个元素并成一组,叫做从m个不同元素中取出n个元素的一个组合;从m个不同元素中取出n(n≤m)个元素的所有组合的个数,叫做从m个不同元素中取出n个元素的组合数。用符号c(m,n) 表示。
咬文嚼字时间结束,向数学大家致敬的同时,看看如何把公式转成代码:
public class TestOrg {
public static void main(String[] args) {
// 排列算法
long pl = arrangement(3, 2);
System.out.println("排列:"+pl); // 排列:6
//组合算法
long zh = combination(3,2);
System.out.println("组合:"+zh); // 组合:3
}
/**
* 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
* 排列个数
* @param n
* @return
*/
private static long factorial(int n) {
return (n > 1) ? n * factorial(n - 1) : 1;
}
/**
* 计算排列数,即A(n, m) = n!/(n-m)!
*
* @param n
* @param m
* @return
*/
public static long arrangement(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) : 0;
}
/**
* 计算组合数,即C(n, m) = n!/((n-m)! * m!)
* @param n
* @param m
* @return
*/
public static long combination(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) / factorial(m) : 0;
}
}
举个栗子
排列选择 和 组合选择
排列选择demo
public class TestArra{
public static void main(String[] args) {
arrangementSelect(new String[] {
"1", "2", "3", "4"
}, 2);
}
/**
* 排列选择(从列表中选择n个排列)
* @param dataList 待选列表
* @param n 选择个数
*/
public static void arrangementSelect(String[] dataList, int n) {
System.out.println(String.format("A(%d, %d) = %d", dataList.length, n, arrangement(dataList.length, n)));
arrangementSelect(dataList, new String[n], 0);
}
/**
* 排列选择
* @param dataList 待选列表
* @param resultList 前面(resultIndex-1)个的排列结果
* @param resultIndex 选择索引,从0开始
*/
private static void arrangementSelect(String[] dataList, String[] resultList, int resultIndex) {
int resultLen = resultList.length;
if (resultIndex >= resultLen) { // 全部选择完时,输出排列结果
System.out.println(Arrays.asList(resultList));
return;
}
// 递归选择下一个
for (int i = 0; i < dataList.length; i++) {
// 判断待选项是否存在于排列结果中
boolean exists = false;
for (int j = 0; j < resultIndex; j++) {
if (dataList[i].equals(resultList[j])) {
exists = true;
break;
}
}
if (!exists) { // 排列结果不存在该项,才可选择
resultList[resultIndex] = dataList[i];
arrangementSelect(dataList, resultList, resultIndex + 1);
}
}
}
/**
* 计算排列数,即A(n, m) = n!/(n-m)!
* @param n
* @param m
* @return
*/
public static long arrangement(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) : 0;
}
/**
* 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
* @param n
* @return
*/
public static long factorial(int n) {
return (n > 1) ? n * factorial(n - 1) : 1;
}
}
输出:
A(4, 2) = 12
[1, 2]
[1, 3]
[1, 4]
[2, 1]
[2, 3]
[2, 4]
[3, 1]
[3, 2]
[3, 4]
[4, 1]
[4, 2]
[4, 3]
组合选择 DEMO
public class TestComb {
public static void main(String[] args) {
combinationSelect(new String[] {
"1", "2", "3", "4", "5"
}, 2);
}
/**
* 计算组合数,即C(n, m) = n!/((n-m)! * m!)
* @param n
* @param m
* @return
*/
public static long combination(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) / factorial(m) : 0;
}
/**
* 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
* @param n
* @return
*/
public static long factorial(int n) {
return (n > 1) ? n * factorial(n - 1) : 1;
}
/**
* 组合选择(从列表中选择n个组合)
* @param dataList 待选列表
* @param n 选择个数
*/
public static void combinationSelect(String[] dataList, int n) {
System.out.println(String.format("C(%d, %d) = %d", dataList.length, n, combination(dataList.length, n)));
combinationSelect(dataList, 0, new String[n], 0);
}
/**
* 组合选择
* @param dataList 待选列表
* @param dataIndex 待选开始索引
* @param resultList 前面(resultIndex-1)个的组合结果
* @param resultIndex 选择索引,从0开始
*/
private static void combinationSelect(String[] dataList, int dataIndex, String[] resultList, int resultIndex) {
int resultLen = resultList.length;
int resultCount = resultIndex + 1;
if (resultCount > resultLen) { // 全部选择完时,输出组合结果
System.out.println(Arrays.asList(resultList));
return;
}
// 递归选择下一个
for (int i = dataIndex; i < dataList.length + resultCount - resultLen; i++) {
resultList[resultIndex] = dataList[i];
combinationSelect(dataList, i + 1, resultList, resultIndex + 1);
}
}
}
输出:
C(5, 2) = 10
[1, 2]
[1, 3]
[1, 4]
[1, 5]
[2, 3]
[2, 4]
[2, 5]
[3, 4]
[3, 5]
[4, 5]
排列选择和组合选择,都是罗列选择结果。
区别是,排列选择是全排列,一个选择内部选择交换了位置,也会认为是一个新的选择。
组合选择里,当一个内部元素的位置发生了变化,会过滤掉,不会认为这是一个新选择。
排列组合乱斗
路飞成长史
public class TestFun {
public static void main(String[] args) {
// 组合选择算法
combinationSelect(new String[] { "路飞打怪", "怪打路飞", "路飞输了开始训练", "路飞赢了开心吃肉"}, 3);
// 排列选择算法
arrangementSelect(new String[] {"路飞打怪", "怪打路飞", "路飞输了开始训练", "路飞赢了开心吃肉" }, 3);
}
/**
* 排列选择(从列表中选择n个排列)
*
* @param dataList
* 待选列表
* @param n
* 选择个数
*/
public static void arrangementSelect(String[] dataList, int n) {
System.out.println(String.format("A(%d, %d) = %d", dataList.length, n, arrangement(dataList.length, n)));
arrangementSelect(dataList, new String[n], 0);
}
/**
* 排列选择
*
* @param dataList
* 待选列表
* @param resultList
* 前面(resultIndex-1)个的排列结果
* @param resultIndex
* 选择索引,从0开始
*/
private static void arrangementSelect(String[] dataList, String[] resultList, int resultIndex) {
int resultLen = resultList.length;
if (resultIndex >= resultLen) { // 全部选择完时,输出排列结果
System.out.println(Arrays.asList(resultList));
return;
}
// 递归选择下一个
for (int i = 0; i < dataList.length; i++) {
// 判断待选项是否存在于排列结果中
boolean exists = false;
for (int j = 0; j < resultIndex; j++) {
if (dataList[i].equals(resultList[j])) {
exists = true;
break;
}
}
if (!exists) { // 排列结果不存在该项,才可选择
resultList[resultIndex] = dataList[i];
arrangementSelect(dataList, resultList, resultIndex + 1);
}
}
}
/**
* 计算排列数,即A(n, m) = n!/(n-m)!
*
* @param n
* @param m
* @return
*/
public static long arrangement(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) : 0;
}
/**
* 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
*
* @param n
* @return
*/
public static long factorial(int n) {
return (n > 1) ? n * factorial(n - 1) : 1;
}
// ===
/**
* 计算组合数,即C(n, m) = n!/((n-m)! * m!)
*
* @param n
* @param m
* @return
*/
public static long combination(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) / factorial(m) : 0;
}
// /**
// * 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
// * @param n
// * @return
// */
// public static long factorial(int n) {
// return (n > 1) ? n * factorial(n - 1) : 1;
// }
/**
* 组合选择(从列表中选择n个组合)
*
* @param dataList
* 待选列表
* @param n
* 选择个数
*/
public static void combinationSelect(String[] dataList, int n) {
System.out.println(String.format("C(%d, %d) = %d", dataList.length, n, combination(dataList.length, n)));
combinationSelect(dataList, 0, new String[n], 0);
}
/**
* 组合选择
*
* @param dataList
* 待选列表
* @param dataIndex
* 待选开始索引
* @param resultList
* 前面(resultIndex-1)个的组合结果
* @param resultIndex
* 选择索引,从0开始
*/
private static void combinationSelect(String[] dataList, int dataIndex, String[] resultList, int resultIndex) {
int resultLen = resultList.length;
int resultCount = resultIndex + 1;
if (resultCount > resultLen) { // 全部选择完时,输出组合结果
System.out.println(Arrays.asList(resultList));
return;
}
// 递归选择下一个
for (int i = dataIndex; i < dataList.length + resultCount - resultLen; i++) {
resultList[resultIndex] = dataList[i];
combinationSelect(dataList, i + 1, resultList, resultIndex + 1);
}
}
}
输出:
C(4, 3) = 4
[路飞打怪, 怪打路飞, 路飞输了开始训练]
[路飞打怪, 怪打路飞, 路飞赢了开心吃肉]
[路飞打怪, 路飞输了开始训练, 路飞赢了开心吃肉]
[怪打路飞, 路飞输了开始训练, 路飞赢了开心吃肉]
A(4, 3) = 24
[路飞打怪, 怪打路飞, 路飞输了开始训练]
[路飞打怪, 怪打路飞, 路飞赢了开心吃肉]
[路飞打怪, 路飞输了开始训练, 怪打路飞]
[路飞打怪, 路飞输了开始训练, 路飞赢了开心吃肉]
[路飞打怪, 路飞赢了开心吃肉, 怪打路飞]
[路飞打怪, 路飞赢了开心吃肉, 路飞输了开始训练]
[怪打路飞, 路飞打怪, 路飞输了开始训练]
[怪打路飞, 路飞打怪, 路飞赢了开心吃肉]
[怪打路飞, 路飞输了开始训练, 路飞打怪]
[怪打路飞, 路飞输了开始训练, 路飞赢了开心吃肉]
[怪打路飞, 路飞赢了开心吃肉, 路飞打怪]
[怪打路飞, 路飞赢了开心吃肉, 路飞输了开始训练]
[路飞输了开始训练, 路飞打怪, 怪打路飞]
[路飞输了开始训练, 路飞打怪, 路飞赢了开心吃肉]
[路飞输了开始训练, 怪打路飞, 路飞打怪]
[路飞输了开始训练, 怪打路飞, 路飞赢了开心吃肉]
[路飞输了开始训练, 路飞赢了开心吃肉, 路飞打怪]
[路飞输了开始训练, 路飞赢了开心吃肉, 怪打路飞]
[路飞赢了开心吃肉, 路飞打怪, 怪打路飞]
[路飞赢了开心吃肉, 路飞打怪, 路飞输了开始训练]
[路飞赢了开心吃肉, 怪打路飞, 路飞打怪]
[路飞赢了开心吃肉, 怪打路飞, 路飞输了开始训练]
[路飞赢了开心吃肉, 路飞输了开始训练, 路飞打怪]
[路飞赢了开心吃肉, 路飞输了开始训练, 怪打路飞]
mac升级计划演示组合选择
2018款的15寸的mbp,在官方配置的基础上的,提供了几项升级,比如
- 升级1T固态
- 升级32G内存
- 升级i9处理器
假设我们选择其中两项目升级,那么显然应该采用组合选择。
public class TestFun {
public static void main(String[] args) {
// 排列选择算法
System.out.println("排列 选择");
arrangementSelect(new String[] {"升级1T固态", "升级32G内存", "升级i9处理器" }, 2);
// 组合选择算法
System.out.println("组合 选择");
combinationSelect(new String[] { "升级1T固态", "升级32G内存", "升级i9处理器"}, 2);
}
/**
* 排列选择(从列表中选择n个排列)
*
* @param dataList
* 待选列表
* @param n
* 选择个数
*/
public static void arrangementSelect(String[] dataList, int n) {
System.out.println(String.format("A(%d, %d) = %d", dataList.length, n, arrangement(dataList.length, n)));
arrangementSelect(dataList, new String[n], 0);
}
/**
* 排列选择
*
* @param dataList
* 待选列表
* @param resultList
* 前面(resultIndex-1)个的排列结果
* @param resultIndex
* 选择索引,从0开始
*/
private static void arrangementSelect(String[] dataList, String[] resultList, int resultIndex) {
int resultLen = resultList.length;
if (resultIndex >= resultLen) { // 全部选择完时,输出排列结果
System.out.println(Arrays.asList(resultList));
return;
}
// 递归选择下一个
for (int i = 0; i < dataList.length; i++) {
// 判断待选项是否存在于排列结果中
boolean exists = false;
for (int j = 0; j < resultIndex; j++) {
if (dataList[i].equals(resultList[j])) {
exists = true;
break;
}
}
if (!exists) { // 排列结果不存在该项,才可选择
resultList[resultIndex] = dataList[i];
arrangementSelect(dataList, resultList, resultIndex + 1);
}
}
}
/**
* 计算排列数,即A(n, m) = n!/(n-m)!
*
* @param n
* @param m
* @return
*/
public static long arrangement(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) : 0;
}
/**
* 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
*
* @param n
* @return
*/
public static long factorial(int n) {
return (n > 1) ? n * factorial(n - 1) : 1;
}
// ===
/**
* 计算组合数,即C(n, m) = n!/((n-m)! * m!)
*
* @param n
* @param m
* @return
*/
public static long combination(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) / factorial(m) : 0;
}
// /**
// * 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
// * @param n
// * @return
// */
// public static long factorial(int n) {
// return (n > 1) ? n * factorial(n - 1) : 1;
// }
/**
* 组合选择(从列表中选择n个组合)
*
* @param dataList
* 待选列表
* @param n
* 选择个数
*/
public static void combinationSelect(String[] dataList, int n) {
System.out.println(String.format("C(%d, %d) = %d", dataList.length, n, combination(dataList.length, n)));
combinationSelect(dataList, 0, new String[n], 0);
}
/**
* 组合选择
*
* @param dataList
* 待选列表
* @param dataIndex
* 待选开始索引
* @param resultList
* 前面(resultIndex-1)个的组合结果
* @param resultIndex
* 选择索引,从0开始
*/
private static void combinationSelect(String[] dataList, int dataIndex, String[] resultList, int resultIndex) {
int resultLen = resultList.length;
int resultCount = resultIndex + 1;
if (resultCount > resultLen) { // 全部选择完时,输出组合结果
System.out.println(Arrays.asList(resultList));
return;
}
// 递归选择下一个
for (int i = dataIndex; i < dataList.length + resultCount - resultLen; i++) {
resultList[resultIndex] = dataList[i];
combinationSelect(dataList, i + 1, resultList, resultIndex + 1);
}
}
}
输出:
排列 选择
A(3, 2) = 6
[升级1T固态, 升级32G内存]
[升级1T固态, 升级i9处理器]
[升级32G内存, 升级1T固态]
[升级32G内存, 升级i9处理器]
[升级i9处理器, 升级1T固态]
[升级i9处理器, 升级32G内存]
组合 选择
C(3, 2) = 3
[升级1T固态, 升级32G内存]
[升级1T固态, 升级i9处理器]
[升级32G内存, 升级i9处理器]
.
.
升级版 单个方向多选,指定过滤元素
在上面的例子中,我们每个升级方向只提供了一个选项,那么是每个方向多个选择呢?
比如,硬盘方向有3个选择:
- SSD-1T版
- SSD-2T版
- SSD-3T版
内存也有三个选择:
- 内存32G
- 内存64G
- 内存128G
(请忽略显示是否配到这么大的容量,一切只是为了演示)
那么,按照原有的算法,结果有15种:
C(6, 2) = 15
[SSD-3T版, SSD-2T版]
[SSD-3T版, SSD-1T版]
[SSD-3T版, 内存128G]
[SSD-3T版, 内存32G]
[SSD-3T版, 内存64G]
[SSD-2T版, SSD-1T版]
[SSD-2T版, 内存128G]
[SSD-2T版, 内存32G]
[SSD-2T版, 内存64G]
[SSD-1T版, 内存128G]
[SSD-1T版, 内存32G]
[SSD-1T版, 内存64G]
[内存128G, 内存32G]
[内存128G, 内存64G]
[内存32G, 内存64G]
显然,这不是我们想要的结果。
重复地 加内存和内存之类的是什么鬼?现加一个3T的,再加一个2T的?开什么玩笑。
我们应该做到每一个方向都只能有一个选项出现在最后的筛选结果。
解决办法
1、取出组合选择结果,这步不变
2、筛选数据时,传入原有的方向集,几个小的Set,每个Set代表一个方向
3、将每一个 组合选择 的结果与每个方向的Set做交集运算,如果交集大于2,则放弃。
3步做完,即可。
public class TestFun {
public static void main(String[] args) {
// 排列选择算法
// System.out.println("排列 选择");
// arrangementSelect(new String[] {"1", "2", "3","4", "5", "6" }, 2);
// 方向一
Set<String> set1 = new HashSet<String>();
set1.add("SSD-1T版");// SSD-1T版
set1.add("SSD-2T版");// SSD-2T版
set1.add("SSD-3T版");// SSD-3T版
// 方向二
Set<String> set2 = new HashSet<String>();
set2.add("内存32G"); // 内存32G
set2.add("内存64G"); // 内存64G
set2.add("内存128G"); // 内存128G
Set<String> allDataSet = new HashSet<String>();
allDataSet.addAll(set1);
allDataSet.addAll(set2);
// 总的元素
String[] dataSetAsArray = allDataSet.toArray(new String[allDataSet.size()]);
List<Set<String>> noPepeatingList = new ArrayList<>();
noPepeatingList.add(set1);
noPepeatingList.add(set2);
// 组合选择算法
System.out.println("组合 选择");
// 有多少个方法,就应该有多少种组合。
// 所以的combinationSelect第二个参数我们传 noPepeatingList.size()
// 第三个传每个方向原有的元素集,方便后面比较交集过滤
combinationSelect(dataSetAsArray, noPepeatingList.size(), noPepeatingList);
//combinationSelect(dataSetAsArray, 2,null);
}
/**
* 排列选择(从列表中选择n个排列)
*
* @param dataList
* 待选列表
* @param n
* 选择个数
*/
public static void arrangementSelect(String[] dataList, int n) {
System.out.println(String.format("A(%d, %d) = %d", dataList.length, n, arrangement(dataList.length, n)));
arrangementSelect(dataList, new String[n], 0);
}
/**
* 排列选择
*
* @param dataList
* 待选列表
* @param resultList
* 前面(resultIndex-1)个的排列结果
* @param resultIndex
* 选择索引,从0开始
*/
private static void arrangementSelect(String[] dataList, String[] resultList, int resultIndex) {
int resultLen = resultList.length;
if (resultIndex >= resultLen) { // 全部选择完时,输出排列结果
System.out.println(Arrays.asList(resultList));
List<String> strings = Arrays.asList(resultList);
strings.size();
return;
}
// 递归选择下一个
for (int i = 0; i < dataList.length; i++) {
// 判断待选项是否存在于排列结果中
boolean exists = false;
for (int j = 0; j < resultIndex; j++) {
if (dataList[i].equals(resultList[j])) {
exists = true;
break;
}
}
if (!exists) { // 排列结果不存在该项,才可选择
resultList[resultIndex] = dataList[i];
arrangementSelect(dataList, resultList, resultIndex + 1);
}
}
}
/**
* 计算排列数,即A(n, m) = n!/(n-m)!
*
* @param n
* @param m
* @return
*/
public static long arrangement(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) : 0;
}
/**
* 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
*
* @param n
* @return
*/
public static long factorial(int n) {
return (n > 1) ? n * factorial(n - 1) : 1;
}
// ===
/**
* 计算组合数,即C(n, m) = n!/((n-m)! * m!)
*
* @param n
* @param m
* @return
*/
public static long combination(int n, int m) {
return (n >= m) ? factorial(n) / factorial(n - m) / factorial(m) : 0;
}
// /**
// * 计算阶乘数,即n! = n * (n-1) * ... * 2 * 1
// * @param n
// * @return
// */
// public static long factorial(int n) {
// return (n > 1) ? n * factorial(n - 1) : 1;
// }
/**
* 组合选择(从列表中选择n个组合)
*
* @param dataList
* 待选列表
* @param n
* 选择个数
*/
public static void combinationSelect(String[] dataList, int n, List<Set<String>> noPepeatingList) {
System.out.println(String.format("C(%d, %d) = %d", dataList.length, n, combination(dataList.length, n)));
combinationSelect(dataList, 0, new String[n], 0, noPepeatingList);
}
/**
* 组合选择
*
* @param dataList
* 待选列表
* @param dataIndex
* 待选开始索引
* @param resultList
* 前面(resultIndex-1)个的组合结果
* @param resultIndex
* 选择索引,从0开始
* @param noPepeatingList
* 可变参数,自身不允许重复的数据
*/
private static void combinationSelect(String[] dataList, int dataIndex, String[] resultList, int resultIndex,
List<Set<String>> noPepeatingList) {
int resultLen = resultList.length;
int resultCount = resultIndex + 1;
if (resultCount > resultLen) { // 全部选择完时,输出组合结果
Set<String> staffsSet = new HashSet<String>(Arrays.asList(resultList));
Set<String> reSultString = new HashSet<String>(Arrays.asList(resultList));
//List<String> reSultString = Arrays.asList(resultList);
if (noPepeatingList != null) {
boolean isContain = false;
for (Set<String> tempSet : noPepeatingList) {
// 交集
Set<String> intersectionSet = new HashSet<String>();
intersectionSet.addAll(tempSet);
// 拿出交集,关键点。
intersectionSet.retainAll(reSultString);
//如果交集的数量大于2,那么代表和某个子集重复。
// 排除数据,不允许存在跟自身原有数据集重复的元素,比如 1,2 在 1,2,3里面,应该排除掉
if (intersectionSet.size()>=2) {
isContain = true;
break;
}
}
if (!isContain) {
System.out.println(reSultString);
}
} else {
System.out.println(reSultString);
}
return;
}
// 递归选择下一个
for (int i = dataIndex; i < dataList.length + resultCount - resultLen; i++) {
resultList[resultIndex] = dataList[i];
combinationSelect(dataList, i + 1, resultList, resultIndex + 1, noPepeatingList);
}
}
}
输出:
组合 选择
C(6, 2) = 15
[SSD-3T版, 内存128G]
[SSD-3T版, 内存32G]
[SSD-3T版, 内存64G]
[SSD-2T版, 内存128G]
[SSD-2T版, 内存32G]
[SSD-2T版, 内存64G]
[SSD-1T版, 内存128G]
[SSD-1T版, 内存32G]
[SSD-1T版, 内存64G]
没错,才是我们想要的结果。
那么如果我们有3个方向呢
试一下:
// 方向一
Set<String> set1 = new HashSet<String>();
set1.add("SSD-1T版");// SSD-1T版
set1.add("SSD-2T版");// SSD-2T版
set1.add("SSD-3T版");// SSD-3T版
// 方向二
Set<String> set2 = new HashSet<String>();
set2.add("内存32G"); // 内存32G
set2.add("内存64G"); // 内存64G
set2.add("内存128G"); // 内存128G
// 方向三
Set<String> set3 = new HashSet<>();
set3.add("处理器i9版"); // 处理器i9
set3.add("处理器未来i10版"); // 处理器未来i10
set3.add("处理器未来i11版"); // 处理器未来i11
Set<String> allDataSet = new HashSet<String>();
allDataSet.addAll(set1);
allDataSet.addAll(set2);
allDataSet.addAll(set3);
// 总的元素
String[] dataSetAsArray = allDataSet.toArray(new String[allDataSet.size()]);
List<Set<String>> noPepeatingList = new ArrayList<>();
noPepeatingList.add(set1);
noPepeatingList.add(set2);
noPepeatingList.add(set3);
// 组合选择算法
System.out.println("组合 选择");
// 有多少个方法,就应该有多少种组合。
// 所以的combinationSelect第二个参数我们传 noPepeatingList.size()
// 第三个传每个方向原有的元素集,方便后面比较交集过滤
combinationSelect(dataSetAsArray, noPepeatingList.size(), noPepeatingList);
输出:
组合 选择
C(9, 3) = 84
[处理器i9版, SSD-3T版, 内存128G]
[处理器i9版, SSD-3T版, 内存32G]
[处理器i9版, SSD-3T版, 内存64G]
[处理器i9版, SSD-2T版, 内存128G]
[处理器i9版, SSD-2T版, 内存32G]
[处理器i9版, SSD-2T版, 内存64G]
[处理器i9版, SSD-1T版, 内存128G]
[处理器i9版, SSD-1T版, 内存32G]
[处理器i9版, SSD-1T版, 内存64G]
[SSD-3T版, 内存128G, 处理器未来i10版]
[SSD-3T版, 内存128G, 处理器未来i11版]
[SSD-3T版, 处理器未来i10版, 内存32G]
[SSD-3T版, 处理器未来i10版, 内存64G]
[SSD-3T版, 内存32G, 处理器未来i11版]
[SSD-3T版, 处理器未来i11版, 内存64G]
[SSD-2T版, 内存128G, 处理器未来i10版]
[SSD-2T版, 内存128G, 处理器未来i11版]
[SSD-2T版, 处理器未来i10版, 内存32G]
[SSD-2T版, 处理器未来i10版, 内存64G]
[SSD-2T版, 内存32G, 处理器未来i11版]
[SSD-2T版, 处理器未来i11版, 内存64G]
[SSD-1T版, 内存128G, 处理器未来i10版]
[SSD-1T版, 内存128G, 处理器未来i11版]
[SSD-1T版, 处理器未来i10版, 内存32G]
[SSD-1T版, 处理器未来i10版, 内存64G]
[SSD-1T版, 内存32G, 处理器未来i11版]
[SSD-1T版, 处理器未来i11版, 内存64G]
没错,27种结果。
每一种结果都是 一个硬盘 + 一个内存 + 一个处理器选择。
绝无重复。
废话终于说完了。
最后,感谢用cgs1999的Java实现排列、组合算法。
本文完。
网友评论