这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
前言
关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!
题目描述
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
链接:leetcode-cn.com/problems/su…
题解
解法一:组合数
这道题目可以看作和 leetcode77类似的题目,77 题是典型的组合数题目,从 nums 数组中选择 k 个数组成新的数组,共可以组成多少个数组。而对应这道题,k 可以从 0 到 nums.length 依次增加,这样就转换为组合数题目了。代码见下方
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function(nums) {
let ans = [[]]
let curr = []
for (let i = 1; i <= nums.length; i++) {
Comb(nums, 0, i, 0, ans, curr)
}
return ans
}
var Comb = (nums, d, k, s, ans, curr) => {
if (d === k) {
ans.push([...curr])
return
}
for (let i = s; i < nums.length; i++) {
curr.push(nums[i])
Comb(nums, d+1, k, i+1, ans, curr)
curr.pop()
}
}
时间复杂度 O(n * 2^n)
解法二:位运算
位运算本质是利用二进制的一些特性来模拟 dfs 过程。对应这道题,我们假设有一个二进制数,这个数每个位的只能取 0 或者 1,该位为 0,代表对应 nums 的元素不被选择,如果为 1,则表示该元素被选择。那么,当这个二进制数从 0 增大到所有位数都为 1 的过程中,就模拟出了 nums 的选择过程。具体怎么对应其实就是一个与运算。可以具体来看代码:
/**
* @param {number[]} nums
* @return {number[][]}
*/
var subsets = function(nums) {
let len = nums.length
let max = 1 << len
let ans = []
for (let mask = 0; mask < max; mask++) {
let curr = []
for (let i = 0; i < len; i++) {
if (mask & 1 << i) { // 这里判断哪个元素对应二进制位置为 1
curr.push(nums[i])
}
}
ans.push(curr)
}
return ans
}
时间复杂度 O(n * 2^n)