LeetCode 👉 HOT 100 👉 子集 - 中等题

88 阅读3分钟

「这是我参与2022首次更文挑战的第6天,活动详情查看:2022首次更文挑战」。

题目

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

示例1

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

输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]

示例2

输入:nums = [0]

输出:[[],[0]]

思路

首先可以考虑到,题目求的是所有不重复的子集,每个数组 nums 中的每个元素,在子集中的状态其实都只有两种,在子集中 或者 不在子集中,那么所有子集的数量应该为 2 ^ n (n = nums.length),可以用来验证答案是否完整。

针对 nums = [1,2,3] 先举例一些子集情况:

[1]

    [1, 2]

        [1, 2, 3]

    [1, 3]

[2]

    [2, 3]

[3]

不难发现,上述子集如果按照这个顺序排列,可以归纳出一个规律:基于已有子集,从剩下的元素中,添加一个元素,可以形成新的子集

比如,对于子集 [1],可以从 i = 1 开始,在剩下的元素中,依次加入子集 [1],形成新的子集 [1,2], [1, 3];

同时新的子集 [1, 2] 又可以从 i = 2 开始,在剩下的元素中,形成新的子集 [1, 2, 3],这时会发现 i == 3,在继续按照这个规律遍历下去,数组索引会越界了,那么就回头看子集 [1, 3],这时同样 i == 3

那就再回头看子集 [2],可以按照如上方法继续获得子集 [2, 3],依次类推,其实上述流程,就是 dfs 回溯算法;

按照上述思路,可以写出如下解法:

dfs 完整代码

    /**
     * @param {number[]} nums
     * @return {number[][]}
     */
    var subsets = function (nums) {
        const n = nums.length;
        // 空集也是子集
        const ans = [[]];

        // 定义dfs:基于当前子集,在剩下的元素中,寻找新子集
        const dfs = (index, list) => {
            for(let i = index; i < n; i++) {

                // 新的子集
                let temp = [...list, nums[i]];

                // 放入结果数组中
                ans.push(temp);

                // 用新的子集,新的位置,寻找下一个子集
                dfs(i + 1, temp);
            }
        }

        // 从初始条件,位置 0,子集[], 开始寻找
        dfs(0, []);
        return ans;
    };

小结

如果没有思路的时候,可以尝试用一些简单的初始条件,去寻找可能存在的规律,也许会对思路有一些帮助

回溯算法对于寻找子集,是比较适合的一种解法,根本思想是先横向遍历,选第一个,基于当前已获得的数据,再纵向遍历数据;当纵向遍历到头,再反过来开始横向遍历的第二个,依次类推

# LeetCode 👉 HOT 100 👉 子集 - 中等题

合集:LeetCode 👉 HOT 100,有空就会更新,大家多多支持,点个赞👍

如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄