输入:若干个集合,各集合中的元素不会重复
输出:求这些集合的笛卡尔积(每个集合中取一个元素所构成的所有可能组合)
例如:
输入:N个集合(例如这里N=3) :<a,b><x,y><1,2,3>
输出: <<a,x,1>, <a,x,2>,… …, <b,y,3>>
注意: 输入集合的个数N不确定
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* 笛卡尔积
*
* 类名称: Descartes.java
* 类描述: 求N个集合的笛卡尔积
* 创建人: leo.Yu
* 创建时间: 2020:03:30 20:50
* 版本: [v1.0]
**/
public class Descartes {
public static void main(String[] args) {
List<List<String>> datas = new ArrayList<>();
datas.add(Arrays.asList("a", "b"));
datas.add(Arrays.asList("x", "y"));
datas.add(Arrays.asList("1", "2","3"));
List<List<String>> descartesResult = getDescartesResult(datas);
System.out.println(descartesResult);
}
/**
*
* @param datas 算法计算的数组
* @param <T> 计算的子集元素类型
* @return
*/
private static <T> List<List<T>> getDescartesResult(List<List<T>> datas) {
List<List<T>> returnList = new ArrayList<>();
descartesRecursive(datas, 0, returnList, new ArrayList<T>());
return returnList;
}
/**
* 递归实现
* 原理:从原始list的0开始依次遍历到最后
* @param originalList 原始list
* @param position 当前递归在原始list的position
* @param resultList 返回结果
* @param cacheList 临时保存的list
*/
private static <T> void descartesRecursive(List<List<T>> originalList, int position, List<List<T>> resultList, List<T> cacheList) {
List<T> originalItemList = originalList.get(position);
for (int i = 0; i < originalItemList.size(); i++) {
//最后一个复用cacheList,节省内存
List<T> childCacheList = (i == originalItemList.size() - 1) ? cacheList : new ArrayList<>(cacheList);
childCacheList.add(originalItemList.get(i));
if (position == originalList.size() - 1) {//遍历到最后退出递归
resultList.add(childCacheList);
continue;
}
descartesRecursive(originalList, position + 1, resultList, childCacheList);
}
}
}