题目
题目来源:力扣(LeetCode)
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
思路分析
回溯
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function (nums) {
const t = []; // 子集
const ans = [];
const dfs = (cur) => {
if (cur === nums.length) { // 指针越界
ans.push(t.slice()); // 将当前子集加入解集
return; // 结束当前递归
}
t.push(nums[cur]); // 选择当前数
dfs(cur + 1, nums); // 基于选择的这个数,继续往下递归,考察下一个数
t.pop(t.length - 1); // 撤销选择当前数
dfs(cur + 1, nums); // 不选择这个数后,继续往下递归,考察下一个数
}
dfs(0, nums);
return ans;
};
二进制 + 位运算
数组的子集个数为 1 << n ,即 2^n,其中n为数组的元素总数
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function (nums) {
const ans = [];
const n = nums.length;
// 数组的子集个数为 1 << n ,即 2^n
// 遍历所有子集
for (let mask = 0; mask < (1 << n); ++mask) {
const t = []; // 存放元素的子集,子集个数总共为 1 << n ,即 2^n
for (let i = 0; i < n; ++i) {
// 构造数字代表的集合,各元素存储至 t 子集中
// 1 << i 即为构造nums数组的第 i 个元素
// 若 mask & (1 << i) 为真,表示当前的 nums[i]不在当前的子集中,则nums[i]放入 t 子集中
if (mask & (1 << i)) {
t.push(nums[i]);
}
}
ans.push(t);
}
return ans;
};