LeetCode78子集
描述
给你一个整数数组
nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例
1
2 输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
思路
子集问题是从 n 个元素的集合中找出满足某种性质的子集。
对于集合中的每个元素有两种状态——在集合中和不在集合中,因此可以使用暴力搜索——回溯法进行求解,穷举每一个元素的状态。
采用回溯法一般需要找出问题的解空间树,然后对解空间树采用深度搜索策略对答案进行搜索。
子集问题的解空间树叫做子集树,因此子集树是问题【在给定n个元素的集合中找出满足某种性质的子集】的响应解空间,典型的01背包问题就可以采用回溯法进行求解。
该问题的解空间树如下所示:
在解空间树中,一个节点代表一个状态,每一层代表你在第几层函数中(可以看做是你在第几层递归中)。
比如下面这张图,这个状态就代表第k层你对第k个元素做的选择。由于每个元素只存在两种状态,所以就对这两种状态进行列举——即选和不选。当所有元素都列举完的时候,就得到了一个子集。然后所有子集加入结果集中。
该问题还有一种形式的解空间树,就是采用类似排列树的方式去得到子集。
以下是另一种解空间树(决策的遍历)的形态。
以[1,2,3]为例,第一个位置有三种选择(选择列表),分别是【1】【2】【3】。第一个位置放了【1】后,第二个位置就只能放置【2】或者【3】,所以下一层的选择列表是【2】【3】。下一个位置只能选择当前位置后面的元素。所以此时第k层的状态就是第k个位置上可以放置的元素。
其实不同的解空间树代表着不同的决策方式,所以我们写算法的重点就在决策方式,深度搜索和回溯只是一种辅助手法。
代码
1 | class Solution { |