子集
- leetcode78 子集
- 题目描述
- 子集问题的解题思路
- 代码框架
- 子集解题代码
- 动态规划专题
leetcode78 子集
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subsets
题目描述
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
nums 中的所有元素 互不相同
子集问题的解题思路
子集问题是不考虑顺序的。
这题我们用回溯算法,首先介绍下回溯算法的解题套路
回溯算法的本质是暴力递归,遍历所有的可能性分支(决策分支)。
解决一个回溯问题,实际上就是遍历一个决策树的过程,在每一个回溯的节点上,都要注意三个问题:
1.已经做出的选择,
2.可以继续做出的选择
3.结束条件:也就是到了无法做出决策的条件
回到这题,我们先演示下,决策的过程,
1.什么都不选的空子集 s_0
和只选择一个元素的子集s_1
第二步,可以继续做出的选择
1下面可以继续做出的选择是2,3,
2下面的选择只有3,因为子集是没有顺序的,因此1不需要再选了
3下面没有可做出的选择了,
也就是结束条件,我们用一个变量去标记,3已经是来到了数组的末尾,没法继续做出选择了,
每次做出选择后,要撤销选择,因为是递归,要保证对递归过程不产生影响,
代码框架
result = []
def process(选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
子集解题代码
class Solution {
List<List<Integer>> res = new LinkedList<>();
// 记录回溯算法的递归路径
LinkedList<Integer> track = new LinkedList<>();
// 主函数
public List<List<Integer>> subsets(int[] nums) {
backtrack(nums, 0);
return res;
}
// 回溯算法核心函数,遍历子集问题的回溯树
public void backtrack(int[] nums, int start) {
res.add(new LinkedList<>(track));
for(int i = start;i < nums.length;i++){
//做出的选择
track.addLast(nums[i]);
//走出选择后,去下一个位置去继续做选择
backtrack(nums,i + 1);
//撤销选择,上一次递归完成后,撤销选择,继续进行下一次递归
track.removeLast();
}
}
}
动态规划专题
将数组分成两个数组,并最小化数组和的差II
将数组分成两个数组,并最小化数组和的差
leetcode337. 打家劫舍 III
leetcode213. 打家劫舍 II
leetcode198. 打家劫舍
动态规划–整数拆分问题