背下来 !!当模板用!!
1.78. 子集
题目描述:
给你一个整数数组 nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例:
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
解答描述:
要求解所有可能的子集,有两种方法,迭代和递归。
关键在于理解:每个元素要么在子集中,要么不在子集中。
1)迭代:
在迭代法中,用长为n的01序列来表示各个元素被选中的情况,共有2^n个序列表示2^n的子集。
2)递归:
背下来 ,当模板,从下标为0开始递归,每个元素要么被选中,要么不被选中,当递归到n的时候将结果压入结果数组中,表示一个子集生成。
代码:
class Solution {
public:
vector<vector<int>> ans;
vector<int> temp;
vector<vector<int>> subsets(vector<int>& nums) {
//每个元素ai要么在子集中,要么不在子集中
int n=nums.size();
for(int i=0;i<pow(2,n);i++)//共2^n个子集
{
temp.clear();
for(int j=0;j<n;j++)//每个子集可用一个长为n的01序列表示
{
if(i & (1<<j))
{
temp.push_back(nums[j]);
}
}
ans.push_back(temp);
}
return ans;
}
};
class Solution {
public:
vector<vector<int>> ans;
vector<int> temp;
void DFS(vector<int>& nums,int index)
{
if(index==nums.size())
{
ans.push_back(temp);
return;
}
//a_index在子集中
temp.push_back(nums[index]);
DFS(nums,index+1);
//a——index不在子集中
temp.pop_back();
DFS(nums,index+1);
}
vector<vector<int>> subsets(vector<int>& nums) {
//每个元素ai要么在子集中,要么不在子集中
DFS(nums,0);
return ans;
}
};
2.90. 子集 II
题目描述:
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例:
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
解答描述:
该题与上一题的区别在于:可能存在重复元素,所以需要进行去重。
去重的方式就是:先进行排序,将相同的元素放在邻近的位置,如果迭代\递归的时候发现没有选择上一个数,且上一个数和当前数相同,那么意味着这轮需要被跳过。
代码:
class Solution {
public:
vector<vector<int>> ans;
vector<int> temp;
//在递归时,若发现没有选择上一个数,且当前数字与上一个数相同,则可以跳过当前生成的子集。
void DFS(vector<int> &nums,int index,bool choose)//choose标记上一个数组是否被选中
{
if(index==nums.size())
{
ans.push_back(temp);
return ;
}
//a_i不在子集中
DFS(nums,index+1,false);
if(choose==false && index>0 && nums[index]==nums[index-1])
{
return;
}
//a_i在子集中
temp.push_back(nums[index]);
DFS(nums,index+1,true);
temp.pop_back();
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
//先对数组进行排序
sort(nums.begin(),nums.end());
DFS(nums,0,false);
return ans;
}
};