标签:void int oid src for blog str https 正数
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例 1:
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题和78.子集的区别在于正数数组中可能包含重复的元素。
39.组合总和与40.组合总和Ⅱ有一定的参考价值。先借鉴对整数数组进行排序的方法,来画图。
总结之前的思路
1.对整数数组进行排序,方便剪枝。剪枝思路是同一层同一个元素只能出现一次。
2.递归从上往下,每一个节点都需要返回,把path加入结果集应该写在回溯函数的最前面。
Arrays.sort(nums);
先排序!!
递归的参数和返回值
nums:输入数组
startIndex:对同一集合进行组合,需要使用startIndex来标记起始区间
List<List<Integer>> res;
List<Integer> path;
void backtracing(int[]nums,int startIndex);
递归的终止条件
这里的思路与78相同,for循环把数组nums从头取到尾,i<nums.length
。
递归的层数是不确定的,终止条件也是取到数组的末尾,也就是startIndex>=nums.length
startIndex >= nums.length
时,i也是大于nums.length是不会进入循环说明这次递归结束,所以这个条件也可以省略。
单层递归逻辑
同一层的同一个元素不能重复,排序之后,同一个元素应该挨着。那么nums[i] == nums[i-1]
来判断是不是重复元素。
取值区间从startIndex开始,i == startIndex
时说明是取值的第一个元素,那他应该直接加入路径并且之前的元素不能取。使用i>startIndex
来控制。
void backtracing(int[]nums,int startIndex){
res.add(new ArrayList(path));
for(int i = startIndex;i<nums.length;i++)
{
if(i>startIndex&&nums[i] == nums[i-1])continue;
path.add(nums[i]);
backtracing(nums,i+1);
path.remove(path.size()-1);
}
}
标签:void int oid src for blog str https 正数
原文地址:https://www.cnblogs.com/rananie/p/14883519.html