这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战
子集
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]] 示例 2:
输入:nums = [0] 输出:[[],[0]]
题解
算法一:DFS回溯(Java)
其实子集也是一种组合问题,因为它的集合是无序的,子集{1,2} 和 子集{2,1}是一样的。
那么既然是无序,取过的元素不会重复取,写回溯算法的时候,for就要从startIndex开始,而不是从0开始!
单看每个元素,都有两种选择:选入子集,或不选入子集。
比如[1,2,3],先看1,选1或不选1,都会再看2,选2或不选2,以此类推。
考察当前枚举的数,基于选它而继续,是一个递归分支;基于不选它而继续,又是一个分支。
- 用索引
index代表当前递归考察的数nums[index]。 - 当
index越界时,说明所有数字考察完了,得到一个解,把它加入解集,结束当前递归分支。
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (nums == null || nums.length == 0) {
List<Integer> list = new ArrayList<Integer>();
result.add(list);
return result;
}
List<Integer> list = new ArrayList<Integer>();
// Arrays.sort(nums);
help(result, nums, list, 0);
return result;
}
private void help(List<List<Integer>> result, int[] nums, List<Integer> list, int start) {
result.add(new ArrayList<>(list));
for (int i = start; i < nums.length; i++) {
list.add(nums[i]);
help(result, nums, list, i+1);
list.remove(list.size() - 1);
}
}
}
时间复杂度:O(N*2^N)
空间复杂度:O(N)
算法二:DFS回溯(Go)
思路同上
func subsets(nums []int) (ans [][]int) {
set := []int{}
var dfs func(int)
dfs = func(cur int) {
if cur == len(nums) {
ans = append(ans, append([]int(nil), set...))
return
}
set = append(set, nums[cur])
dfs(cur + 1)
set = set[:len(set)-1]
dfs(cur + 1)
}
dfs(0)
return
}
时间复杂度:O(N*2^N)
空间复杂度:O(N)