赞
踩
比如有数组[1, 2, 3],其元素数量n = 3,将那么其子集为
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
可以用一共三个方法来求出所有子集,以这题作为参考
每一层代表一个元素,左子树代表不使用该节点,右子树代表使用该节点,使用中序遍历来获得全部叶子结点,那么就能获得该数组的子集。
private void getArr(List<Integer> list, List<List<Integer>> result, List<Integer> temp, int level)
{
if(level == list.size())
{
result.add(temp);
}
else
{
getArr(list, result, new ArrayList<>(temp), level + 1);
temp.add(list.get(level));
getArr(list, result, new ArrayList<>(temp), level + 1);
}
}
因为这个可以划分出比原问题规模小却同质的问题,那么是可以用递归解决的
private List<List<Integer>> getArr(List<Integer> list, List<List<Integer>> result, int index) { if(index == list.size()) { result.add(new ArrayList<>()); } else { List<List<Integer>> arr = new ArrayList<>(getArr(list, result, index + 1)); for(List<Integer> eList : arr) { List<Integer> temp = new ArrayList<Integer>(eList); temp.add(list.get(index)); //给子集的每个数组从小到大排序 temp.sort(Comparator.comparing(Integer::intValue)); result.add(temp); } } return result; }
这个最简单,这题有3个元素,假设这三个元素设为连续的二进制数,1代表选取,0代表不选取,从000 - 111一共有八种情况,也是子集的数量。
private void getArr(List<Integer> list, List<List<Integer>> result) { //子集的数量 int n = 1 << list.size(); List<Integer> temp = null; for(int i = 0; i < n; i ++) { temp = new ArrayList<>(); int j = i; int index = list.size() - 1; //循环前检测j是否是000 while(j > 0) { if((j&1) == 1) { temp.add(list.get(index)); } j = j >> 1; index --; } temp.sort(Comparator.comparing(Integer::intValue)); result.add(temp); } }
经过测试,对于包含元素数量20左右的数组的所有子集,三种方法处理速度都到了1.5-1.8秒左右,到了25之后速度急剧下降,10秒钟也没有结果,因为这三个算法时间复杂度都是O(2^n)级别的
三个算法的思路是参考了这个大佬的博客:
Leetcode:Subsets 求数组的所有子集
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。