1 子集
分析
子集的组成可以看作与集合大小相同的二进制串的所有情况。
- 找到某个二进制数
1
的索引方法:mask < (1 << n)
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
= len(nums)
n = []
ans for mask in range(1 << n): # 最大的值即是1<<n
iter = []
for i in range(n):
if mask & (1 << i): iter.append(nums[i])
iter)
ans.append(return ans
#include <vector>
class Solution {
public:
<int> iter;
vector<vector<int>> ans;
vector<vector<int>> subsets(vector<int>& nums) {
vectorint n = nums.size(); // 最长的子集的长度就是集合元素的个数
for (int mask = 0; mask < (1 << n); ++mask) { // 在0-n-1之中遍历
.clear(); // iter用于存储数对应的二进制
iterfor (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
// 找到mask二进制1的位置
.push_back(nums[i]);
iter}
}
.push_back(iter);
ans}
return ans;
}
};
2 子集Ⅱ
分析
该题和上一题基本一致,但是要注意不包含重复的子集和原集合中元素可以重复,这就要求:
- 数组得先进行排序
- 在将集合放入结果列表中时需要判定数组是否就在其中
#include <vector>
#include <algorithm>
#include <set>
class Solution {
public:
std::vector<std::vector<int>> subsetsWithDup(std::vector<int>& nums) {
std::vector<std::vector<int>> ans;
std::vector<int> iter;
int n = nums.size();
// 对 nums 排序,以便处理重复元素
std::sort(nums.begin(), nums.end());
// 使用 std::set 存储子集,自动去除重复
std::set<std::vector<int>> subsets;
// 使用位掩码生成所有子集
for (int mask = 0; mask < (1 << n); ++mask) {
.clear();
iterfor (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
.push_back(nums[i]);
iter}
}
.insert(iter); // 自动去除重复
subsets}
// 将 std::set 中的子集转换为结果
for (const auto& subset : subsets) {
.push_back(subset);
ans}
return ans;
}
};
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
= []
ans = len(nums)
n
nums.sort()for mask in range(1 << n):
iter = []
for i in range(n):
if mask & (1 << i): iter.append(nums[i])
if iter not in ans:
iter)
ans.append(return ans
3 全排列
分析
回溯法:
迭代地将数放在不同的位置而产生不同的组合,若组合未出现在结果中就加入,否则,将最后一个元素弹出,在该位置迭代其他数。
class Solution {
public:
<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> result;
vector<int> path;
vector(nums, path, result);
dfsreturn result;
}
void dfs (vector<int> nums, vector<int>& path, vector<vector<int>>& result) {
if (path.size() == nums.size()) {
.push_back(path);
resultreturn;
}
for (auto i : nums) {
if (find(path.begin(), path.end(), i) == path.end()) {
.push_back(i);
path(nums, path, result);
dfs.pop_back();
path}
}
}
};
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
= []
result = []
path def dfs(nums: List[int], path: List[int], result: List[List[int]]) -> None:
if len(path) == len(nums):
# 防止浅拷贝的问题
result.append(path[:]) return
for i in nums:
if i not in path:
path.append(i)
dfs(nums, path, result)
path.pop()
dfs(nums, path, result)return result