算法思路:
Leetcode 078的题目。这里作为知识点归纳。
- 递归中i=st开始。
- 回溯: path递归后去恢复状态。
- dfs中传入i+1。
- 结果要复制new ArrayList<>(path)
- 一般来说,终止条件才加入结果,但由于子集任何path修改都是子集,所有立即加入。
和全排列的区别:
- 由于排列可以乱序如[1,2,3]结果是[1,3,2]也就是一个结果需要多次从左向右完全扫描,所以i=0开始且维护visited数组
组合的结果是按照数组顺序的,所以只要从左到右扫描一次即可,所以用i=st。
- 结果方面,排列结果是满长度,而组合不是。所以在加入到res位置上,组合用st来判断是否结束且加入到path就立刻进入最后
结果,而排列是在终结条件上加入。
应用:
- 找所有可能性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| def combine(self, nums: List[int]) -> List[List[int]]: if not nums: return [[]] path, result = [], [] self.dfs(nums, 0, path, result) return result
def dfs(self, nums, st, path, result): if st == len(nums): return
for i in range(st, len(nums)): path.append(nums[i]) result.append(list(path)) self.dfs(nums, i + 1, path, result) path.pop()
|
Java代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public List<List<Integer>> subsets(int[] nums) { List<Integer> path = new ArrayList<>(); List<List<Integer>> res = new ArrayList<>(); res.add(new ArrayList<>(path)); if(nums == null || nums.length == 0) return res; dfs(nums, 0, path, res); return res; }
void dfs(int[] nums, int st, List<Integer> path, List<List<Integer>> res) { if(st == nums.length) return; for(int i = st; i < nums.length; i++) { path.add(nums[i]); res.add(new ArrayList<>(path)); dfs(nums, i + 1, path, res); path.remove(path.size() - 1); } }
|
算法分析:
时间复杂度为O(2n)
,空间复杂度O(1)
。