题目LeetCode78
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入: nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
Python解法
解法一(追加)
python
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = [[]]
for num in nums:
for i in range(len(res)):
res.append(res[i] + [num])
return res
解释
在空集的基础上,循环追加后面的数据
python
for num in nums:
# 把当前结果里的每个子集都拿出来,加上 num,再放回 res
for i in range(len(res)):
res.append(res[i] + [num])
过程演示
以示例为例。
① 处理第一个数:1
把 res 里的每个子集 + [1],再追加进去:
-
\] + \[1\] = \[1
res 变成:[ [], [1] ]
② 处理第二个数:2
把当前 res 里的每个子集 + [2]:
-
\] + \[2\] = \[2
-
1\] + \[2\] = \[1,2
res 变成:[ [], [1], [2], [1,2] ]
③ 处理第三个数:3
把当前 res 里的每个子集 + [3]:
-
\] + \[3\] = \[3
-
1\] + \[3\] = \[1,3
-
2\] + \[3\] = \[2,3
-
1,2\] + \[3\] = \[1,2,3
res 最终:[ [], [1], [2], [1,2], [3], [1,3], [2,3], [1,2,3] ]
解法二(搜索)
python
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
res = []
self.dfs(nums, 0, [], res)
return res
def dfs(self, nums, index, path, res):
res.append(path.copy())
for i in range(index, len(nums)):
path.append(nums[i])
self.dfs(nums, i + 1, path, res)
path.pop()
解释
index:当前走到第几个数
path:当前正在选的子集
res:最终结果
主要是搜索函数。
python
def dfs(self, nums, index, path, res):
# 每一步都把当前路径加入答案
res.append(path.copy())
# 从 index 开始往后选
for i in range(index, len(nums)):
path.append(nums[i]) # 选 nums[i]
self.dfs(nums, i + 1, path, res) # 递归往后
path.pop() # 不选 nums[i],回溯
过程演示
- 一开始:
path = []→ 存[] - 选 1 →
path = [1]→ 存[1]- 再选 2 →
path = [1,2]→ 存[1,2]- 再选 3 →
path = [1,2,3]→ 存[1,2,3] - 不选 3 → 退回
- 再选 3 →
- 不选 2,选 3 →
path = [1,3]→ 存[1,3]
- 再选 2 →
- 不选 1,选 2 →
path = [2]→ 存[2]- 再选 3 →
path = [2,3]→ 存[2,3]
- 再选 3 →
- 不选 1、2,选 3 →
path = [3]→ 存[3]
最后:[[], [1], [1,2], [1,2,3], [1,3], [2], [2,3], [3]]
Java解法
解法一(追加)
java
import java.util.List;
import java.util.ArrayList;
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
// 初始加入空集合
res.add(new ArrayList<>());
// 标准普通for遍历每个数字
for (int k = 0; k < nums.length; k++) {
int num = nums[k];
int size = res.size();
// 遍历当前已存在的所有子集
for (int i = 0; i < size; i++) {
// 复制原有子集
List<Integer> temp = new ArrayList<>(res.get(i));
temp.add(num);
res.add(temp);
}
}
return res;
}
}
解法二(搜索)
java
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
backtrack(nums, 0, new ArrayList<>(), res);
return res;
}
private void backtrack(int[] nums, int index, List<Integer> path, List<List<Integer>> res) {
res.add(new ArrayList<>(path));
for (int i = index; i < nums.length; i++) {
path.add(nums[i]);
backtrack(nums, i + 1, path, res);
path.remove(path.size() - 1);
}
}
}
C++解法
解法一(追加)
cpp
#include <vector>
using namespace std;
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
res.push_back({});
// 标准普通for遍历
for (int k = 0; k < nums.size(); ++k) {
int num = nums[k];
int n = res.size();
for (int i = 0; i < n; ++i) {
vector<int> temp = res[i];
temp.push_back(num);
res.push_back(temp);
}
}
return res;
}
};
解法二(搜索)
cpp
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<vector<int>> res;
vector<int> path;
backtrack(nums, 0, path, res);
return res;
}
void backtrack(vector<int>& nums, int index, vector<int>& path, vector<vector<int>>& res) {
res.push_back(path);
for (int i = index; i < nums.size(); ++i) {
path.push_back(nums[i]);
backtrack(nums, i + 1, path, res);
path.pop_back();
}
}
};