Medium
题目描述
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
1 <= nums.length <= 10-10 <= nums[i] <= 10nums中的所有元素 互不相同
解题思路
解题思路
这道题要求生成一个数组的所有子集,也就是幂集问题。有三种常见的解法:
方法一:回溯法(推荐)
回溯法是最直观的思路。对于每个元素,我们有两种选择:加入当前子集或不加入。通过递归遍历所有可能的选择组合,就能得到所有子集。在递归过程中,我们维护一个当前子集,当遍历完所有元素后,将当前子集加入结果集。
方法二:位操作法
由于子集问题本质上是每个元素选择或不选择的问题,可以用二进制位来表示。对于n个元素,共有2^n个子集,每个子集对应一个从0到2^n-1的二进制数,位为1表示选择该元素,位为0表示不选择。
方法三:迭代法
从空集开始,依次考虑每个元素。对于当前的所有子集,为每个子集创建一个新的子集(在原子集基础上加入当前元素),这样就能逐步构建出所有子集。
回溯法代码清晰易懂,时间复杂度最优,是最推荐的解法。
代码实现
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> result;
vector<int> current;
backtrack(nums, 0, current, result);
return result;
}
private:
void backtrack(vector<int>& nums, int start, vector<int>& current, vector<vector<int>>& result) {
result.push_back(current);
for (int i = start; i < nums.size(); i++) {
current.push_back(nums[i]);
backtrack(nums, i + 1, current, result);
current.pop_back();
}
}
};
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
result = []
def backtrack(start, current):
result.append(current[:])
for i in range(start, len(nums)):
current.append(nums[i])
backtrack(i + 1, current)
current.pop()
backtrack(0, [])
return result
public class Solution {
public IList<IList<int>> Subsets(int[] nums) {
IList<IList<int>> result = new List<IList<int>>();
IList<int> current = new List<int>();
Backtrack(nums, 0, current, result);
return result;
}
private void Backtrack(int[] nums, int start, IList<int> current, IList<IList<int>> result) {
result.Add(new List<int>(current));
for (int i = start; i < nums.Length; i++) {
current.Add(nums[i]);
Backtrack(nums, i + 1, current, result);
current.RemoveAt(current.Count - 1);
}
}
}
var subsets = function(nums) {
const result = [];
const backtrack = (start, current) => {
result.push([...current]);
for (let i = start; i < nums.length; i++) {
current.push(nums[i]);
backtrack(i + 1, current);
current.pop();
}
};
backtrack(0, []);
return result;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(2^n) | 共有2^n个子集,每个子集需要O(n)时间复制 |
| 空间复杂度 | O(n) | 递归栈深度为O(n),不计算结果集的空间 |
相关题目
. Subsets II (Medium)
. Generalized Abbreviation (Medium)
. Letter Case Permutation (Medium)