0
点赞
收藏
分享

微信扫一扫

LeetCode 热题 HOT 100 第33天:“子集”

继续刷LeetCode 热题 HOT 100 的题目,并且在博客更新我的solutions。在csdn博客中我会尽量用文字解释清楚,相关Java代码大家可以前往我的个人博客jinhuaiyu.com中查看。
题目:子集
给你一个整数数组 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 中的所有元素 互不相同

solution 1:动态规划
我们需要找到前i位数字所有子集的集合和前i+1位数字所有子集的集合之间的关系。假设前者的集合为f(i),把其中每个子集都加入数字nums[i+1]形成一组集合add,则f(i+1)就是f(i)+add。这个集合规律大家可以自己写着试试。
一开始,我们要在集合中放入空集(空集是所有集合的子集),然后从0开始遍历nums数组,开始一层层计算f(i)。每层中都把前一层得到的集合取出来复制并都加上数字nums[i],然后放回集合。

solution 2:二进制对应子集
对于所有子集来说,都单独对应于一种nums数组每位取和不取,假设取为1不取为0,对于nums为{5,2,9},子集空集对应二进制数000,子集{5,2}对应于二进制数110。一共有2^n个子集,也就对应2^n种二进制数(n位,n为nums长度)。而且这些二进制数是连续的,其十进制大小从0到 2^n - 1。
我们可以枚举十进制值从0到 2^n - 1的二进制数(n位,前面补0)来得到对应的所有子集。对于其中一个二进制数来说,如果第i位为1,则nums[i]加入当前子集。
为了判断一个十进制数m转换成二进制后第i位是否位1,我们可以用其和2^i求按位与&。因为2^i的二进制数,除了第i位是1其他位都是0,如果m的第i位也是0,则两者按位与必为0,否则为1。

solution 3:回溯(深度优先搜索)
深度优先搜索时,每条路径对应一个不同的子集,深度为nums.length。每层有取和不取nums[i]两种选择,到达叶子结点(第n层)时记录当前路径对应的子集。前面已经做了很多回溯问题了,这道题更简单,每层只有两种选择,可以先把nums[i]加入,然后向下搜索,回溯回来后把这个数字取出,并沿着不取该数往下搜索。

Finally,带有详细注释的代码放在我的个人博客http://jinhuaiyu.com/leetcode-subsets/

举报

相关推荐

0 条评论