「这是我参与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,有空就会更新,大家多多支持,点个赞👍
如果大家有好的解法,或者发现本文理解不对的地方,欢迎留言评论 😄