给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
提示:
1 <= nums.length <= 10
-10 <= nums[i] <= 10
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解读题意,给定一个数组,返回一个二维数组,要求数组中包括所有给定数组的子集,注意子集不能有重复结果,例如[1,2,2],子集包括两个[1,2]返回的数组中只能包括一个
先不考虑重复的情况,我们可以想到从数组中的第一个元素出发,此时有两种选择,拿这个数字或者不拿,可以想到利用递归一种情况是拿,然后回溯(不拿)在深入遍历第二种情况
考虑重复的情况,我们可以利用set进行去重,考虑一种情况[2,1,2]此时它的子集包括[2,1],[1,2]这种情况下只利用set是没办法判断重复的,所以我们在进行递归之前要把给定的数组进行排序,换成[1,2,2]就可以去除多余的[1,2]
考虑需要的变量(递归的参数),首先我们需要一个一维数组用来存储当前拿的数字,然后需要一个set
set<vector<int> > ans_set; //用来去重
vector<int> nowarr; //用来存放当前拿出来的数字
vector<vector<int> > ans; //用来存放答案
ans.push_back(nowarr); //首先把空数组存进答案
我考虑递归分为两步,首先思考当前能做的事情,最后思考出口条件
首先将当前的数字存入数组中,然后在判断这个子集是否出现过,如果没有出现过,就把它记录在答案中,然后直接递归遍历下面的数,遍历完需要回溯(没拿当前数字的情况),然后再递归深入遍历
//现在能做的事情
nowarr.push_back(nums[i]);
if(ans_set.find(nowarr)==ans_set.end())
{
ans.push_back(nowarr);
ans_set.insert(nowarr);
}
recursion_back(nums,nowarr,ans_set,ans,i+1);
nowarr.pop_back(); //回溯(不拿当前的数字)
recursion_back(nums,nowarr,ans_set,ans,i+1);
很简单,当下标的值等于给定数组的大小就返回就好了
//出口
if(i>=nums.size())
return;
class Solution {
public:
//nowarr:当前存放数字的数组 ans存放答案 i存放下标
void recursion_back(vector<int>& nums,vector<int> nowarr,
set<vector<int> > &ans_set,vector<vector<int> > &ans,int i)
{
//出口
if(i>=nums.size())
return;
//现在能做的事情
nowarr.push_back(nums[i]);
if(ans_set.find(nowarr)==ans_set.end())
{
ans.push_back(nowarr);
ans_set.insert(nowarr);
}
recursion_back(nums,nowarr,ans_set,ans,i+1);
nowarr.pop_back(); //回溯(不拿当前的数字)
recursion_back(nums,nowarr,ans_set,ans,i+1);
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
set<vector<int> > ans_set; //用来去重
vector<int> nowarr; //用来存放当前拿出来的数字
vector<vector<int> > ans; //用来存放答案
ans.push_back(nowarr); //首先把空数组存进答案
sort(nums.begin(),nums.end());
recursion_back(nums,nowarr,ans_set,ans,0);
return ans;
}
};
什么样的情况下用递归呢,像这道题,我们如果直接用循环做,我们知道循环的次数不是很容易,一般不容易知道循环次数的题目,直接用递归会方便一些。
如果用循环这道题我的思路是状压,用一个bool类型的数组,每一位0或1代表当前的数字是否要拿