【发布时间】:2017-08-26 16:13:51
【问题描述】:
以下代码查找一组数字的所有子集的复杂度是多少?
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> subsets = new ArrayList<>();
subsets.add(new ArrayList<Integer>());
return find(subsets, nums, 0);
}
private List<List<Integer>> find(List<List<Integer>> subsets, int[] nums, int index) {
if (index == nums.length) {
return subsets;
}
List<List<Integer>> newSubsets = new ArrayList<>();
for (List<Integer> subset: subsets) {
List<Integer> newSubset = new ArrayList<>();
newSubset.addAll(subset);
newSubset.add(nums[index]);
newSubsets.add(newSubset);
}
subsets.addAll(newSubsets);
return find(subsets, nums, index + 1);
}
是O(2^nums.length),因为这是子集的数量,您必须将每个子集添加到返回的列表中吗?另外,我是否认为下面的版本仍然是渐近的O(2^set.size()),但一般递归贡献的空间复杂度是O(set.size()),而在上面的尾递归代码中,它是O(1)?
public static ArrayList<ArrayList<Integer>> getSubsets(ArrayList<Integer> set) {
ArrayList<ArrayList<Integer>> subsets = new ArrayList<>();
getSubsets(set, subsets, 0);
return subsets;
}
private static void getSubsets(ArrayList<Integer> set, ArrayList<ArrayList<Integer>> subsets, int index) {
if (index == set.size()) {
subsets.add(new ArrayList<Integer>());
return;
}
getSubsets(set, subsets, index + 1);
int item = set.get(index);
ArrayList<ArrayList<Integer>> moreSubsets = new ArrayList<>();
for (ArrayList<Integer> subset: subsets) {
ArrayList<Integer> newSubset = new ArrayList<>();
newSubset.addAll(subset);
newSubset.add(item);
moreSubsets.add(newSubset);
}
subsets.addAll(moreSubsets);
}
【问题讨论】:
-
Java 不进行尾调用消除。
-
... 但是现在您只需一步将递归转换为迭代。它会运行得稍微快一些,但是由于缺少方法调用,您不会节省太多内存。经过几次迭代后,子集将分配比堆栈帧多得多的内存。