LeetCode-78-子集


题意描述:

给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明 :解集不能包含重复的子集。


示例:

输入: nums = [1,2,3]
输出:
[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

解题思路:

Alice: 这道题在哪也见过,而且当时没有做出来,😂
Bob: 😂我也没有思路,我们把例子列一列,找找规律吧。
Alice: 那就先写到四个元素的吧。

[ ][1][1, 2][1,2,3 ][1, 2, 3, 4 ]
[ ][ ] , 1[ ], 1, 2, 12[ ], 1, 2, 12, 3, 13, 23, 123

Bob: 这个表格画的不错呀,直接找“通项”公式还是有困难的,不过我好像发现了前后相邻两项之间的关系。
Alice: 相邻两项的递推公式 ? 是把 新增加的元素 在原来的子集上全部添加一遍 吗 ?
Bob: 对,你看 [1,2,3][1,2,3,4] 的子集,假设我们已经求出了 [1,2,3] 的子集,只需要 在 再把 4 这个元素再添加到已有的子集上,然后再加上 [1,2,3]的子集就是[1,2,3,4]的子集了。
Alice: 也就是说[1,2,3,4]的子集可以分为两部分,有 4 的部分好没有 4 的部分。没有 4 的部分就是 [1,2,3] 的幂集,有 4 的部分就是 [1,2,3] 的幂集 全部再加一个 4。
Bob: 然后这就像是斐波那契数列一样,可以用递归的方法来做了。
Alice:😎😎。


代码:

Python 方法一: 递归。

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        return self.getSubsets(nums, [[]])
    
    def getSubsets(self, nums: List[int], ans: List[List[int]]) -> List[List[int]]:

        # 递归的终止条件
        if len(nums) == 0:
            return ans
        else:
            # 每次添加一个 nums[0] 到前面的子集中去
            tmp = []
            for x in ans:
                tmp.append(x + [nums[0]])
            ans.extend(tmp)
            nums.pop(0)
            return self.getSubsets(nums, ans)

Java 方法一: 递归。

class Solution {
    
    int[] nums = null;
    List<List<Integer>> ans = new ArrayList();
    // 减少参数传递

    public List<List<Integer>> subsets(int[] nums) {

        this.nums = nums;
        List<Integer> tmp = new ArrayList();
        this.ans.add(tmp);
        // init

        return getSubsets(0);
    }

    public List<List<Integer>> getSubsets(int index){

        // 递归求解
        if(index == nums.length){
            return this.ans;
        }else{
            int tmpLength = this.ans.size();
            for(int i=0; i<tmpLength; ++i){
                List<Integer> tmp = new ArrayList();
                for(int j=0; j<this.ans.get(i).size(); ++j){
                    tmp.add(this.ans.get(i).get(j));
                }
                tmp.add(this.nums[index]);
                this.ans.add(tmp);
            }
            return getSubsets(index+1);
        }
    }
}

易错点:

  • 一些测试样例:
[]
[1]
[1,2]
[1,2,3]
[1,2,3,4]
  • 答案:
[[]]
[[],[1]]
[[],[1],[2],[1,2]]
[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3],[4],[1,4],[2,4],[1,2,4],[3,4],[1,3,4],[2,3,4],[1,2,3,4]]

总结:

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值