问题
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
分析
受此前全排列问题的启发,解答回溯问题时,可以把模拟的递归path先列出来,再通过观察其变化,确定需要用到的状态变量及其可能的修改。
第一列1表示当前path需要加到res中,即dfs过程;0表示不加,即回溯过程。
1 2 3 4 5 6 7 8 9 10 11 12 13
| 1 1 1 1 2 1 1 2 3 0 1 2 0 1 1 1 3 0 1 0 _ 1 2 1 2 3 0 2 0 _ 1 3
|
- 还是以数组的index作为参数传给dfs,递归终止的条件是index大于nums_len;
- 每次变化的path都需要加到res中;
- 每深一层递归的循环起始位置都应该从上一层递归的index + 1 开始;
- path要有一个回溯的状态更新;
- 因为此题不包含重复元素,且每次循环不需要从index = 0处开始,因此不需要visited数组;
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: def backtrack(index): if index > self.length: return res.append(path.copy()) for i in range(index, self.length): path.append(nums[i]) backtrack(i + 1) path.pop()
res = [] path = [] self.length = len(nums) backtrack(0) return res
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Solution { List<List<Integer>> res = new ArrayList<List<Integer>>(); List<Integer> path = new ArrayList<Integer>(); public List<List<Integer>> subsets(int[] nums) { backtrack(0, nums); return res; } private void backtrack(int index, int[] nums){ if (index > nums.length){return;} res.add(new ArrayList<Integer>(path)); for (int i = index; i < nums.length; ++i){ path.add(nums[i]); backtrack(i + 1, nums); path.remove(path.size()-1); } } }
|