78. 子集
题目描述
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
输入输出
1 2 3 4 5
| 输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
输入:nums = [0] 输出:[[],[0]]
|
基本思路
先回顾一下 46. 全排列 回溯算法的解题模板
1 2 3 4 5 6 7 8 9
| result = [] def backtrack(路径, 选择列表): if 满足结束条件: result.add(路径) return for 选择 in 选择列表: 做选择 backtrack(路径, 选择列表) 撤销选择
|
本题中的代码思路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| vector<int> t; void dfs(int cur, int n) { if (cur == n) { return; } t.push_back(cur); dfs(cur + 1, n); t.pop_back(); dfs(cur + 1, n); }
|
- 在进入
dfs(cur, n)
之前 [0, cur-1]
位置状态已经确定 但是[cur, n-1]
的状态是未知的
- dfs就用于确定状态 并确定
dfs(cur+1, n)
- 对于cur位置需要考虑
nums[cur]
要不要取 如果取 要加入tmp
中 再执行dfs(cur+1, n)
执行结束后需要对tmp进行回溯
- 如果不取,则直接执行
dfs(cur+1,n)
在整个递归调用的过程中,cur
是从小到大递增的,当 cur
增加到 n 的时候,记录答案并终止递归。
- 性能:
- 时间复杂度:$O(n \times 2 ^ n)$ 一共$2^n$个状态,每种状态需要 $O(n)$ 的时间来构造子集。
- 空间复杂度:$O(n)$ 临时数组
tmp
的空间代价是$O(n)$ 递归时栈的空间代价是$O(n)$
java实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { List<Integer> tmp = new ArrayList<Integer>(); List<List<Integer>> res = new ArrayList<List<Integer>>(); public List<List<Integer>> subsets(int[] nums) { dfs(0, nums); return res; }
public void dfs(int cur, int[] nums){ if(cur == nums.length){ res.add(new ArrayList<Integer>(tmp)); return; } tmp.add(nums[cur]); dfs(cur + 1, nums); tmp.remove(tmp.size() - 1); dfs(cur + 1, nums); } }
|