给你一个整数数组 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] <= 10
nums
中的所有元素 互不相同
给你一个整数数组 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
直接先给各位大佬奉上第一题代码
class Solution {
//结果集
public List<List<Integer>> ans=new ArrayList<>();
//路径集合
public List<Integer> path=new ArrayList<>();
//这道题常规回溯稍有区别,一般答案在叶子节点,而这题答案还包括各个枝节点
//所以在path每次添加元素时就得收集结果
public void dfs(int[] nums,int index){
//递归边界,该题每次肯定得搜索到叶子节点
//当起始位置等于数组长度时到达边界返回
if(index==nums.length){
return;
}
for(int i=index;i<nums.length;i++){
path.add(nums[i]);
//这里就得收集答案了
ans.add(new ArrayList<>(path));
//正常往下搜索
dfs(nums,i+1);
//回溯弹出尾元素
path.remove(path.size()-1);
}
}
public List<List<Integer>> subsets(int[] nums) {
//必定存在一个空list,直接加入答案
ans.add(new ArrayList<>(path));
//递归搜索答案,将数组和起始位置传递过去
dfs(nums,0);
return ans;
}
}
第二题区别并不是很大,但是有一个关键细节,例如[1,2,2],按照第一题搜索是会出现两个[2]结果,重复了,这里的去重就是关键点,还是拿[1,2,2]举例子,如果当前数组元素和下一个元素相同,那么我起始搜索肯定会重复,在i=1时,会加入答案[2],而在i=2时还会有相同答案,若后面还有元素肯定都会重复,所以这个时候我们必须跳过相同数组元素,下面奉上代码
class Solution {
public List<List<Integer>> ans=new ArrayList<>();
public List<Integer> path=new ArrayList<>();
public void dfs(int[] nums,int index){
if(index==nums.length)return;
for(int i=index;i<nums.length;i++){
//index起始位置为0,当i!=index时也就是i是大于0的
//为了防止越界,我们采用当前元素和上一个元素比较,只需保证i-1>=0就行
if(i!=index&&nums[i]==nums[i-1])continue;
path.add(nums[i]);
ans.add(new ArrayList<>(path));
dfs(nums,i+1);
path.remove(path.size()-1);
}
}
public List<List<Integer>> subsetsWithDup(int[] nums) {
//这里必须要进行排序以确保相同元素在相邻位置
Arrays.sort(nums);
ans.add(path);
dfs(nums,0);
return ans;
}
}