0
下面的代碼查找一組數字的所有子集的複雜性如何?遞歸和尾遞歸代碼的運行時間和空間複雜度
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沒有做尾調用消除。 – user2357112
...但現在你只是將遞歸轉換爲迭代的一個步驟。它會運行得稍微快一些,但不會因缺少方法調用而節省太多內存。經過幾次迭代後,子集將分配比堆棧多得多的內存。 – Selindek