java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846 |
---|
文章目录
解题思路:时间复杂度O( n 2 ∗ n n^2*n n2∗n),空间复杂度O(n) |
---|
- 78题的衍生题,不同点在于,这道题会有重复元素。所以每个元素入集合时,需要判断
- 所以我们先排序,让其有序,方便我们判断重复元素
- 每个元素有两种状态,选和不选
- 每个元素默认不选,不选的时候,无需进行判断
- 要选择当前元素时,要进行判断,是否是重复元素(和前一个元素是否一样),如果是,就放弃当前元素的枚举,因为必然会重复
- 具体查看代码注释中的例子
🏆LeetCode78. 子集https://blog.csdn.net/grd_java/article/details/136646871 |
---|
代码 |
---|
class Solution {
/**
1 2 2 获得子集
不选 不选 不选 []
不选 不选 前一个没选,而且和前一个一样,不选
不选 前一个没选,和前一个不一样,选 不选 [2]
不选 选 选 [2,2]
选 不选 不选 [1]
选 不选 前一个没选,和前一个一样,不选
选 前一个选了,这个也选 不选 [1,2]
选 选 前一个选了,这个也选 [1,2,2]
*/
int[] nums;
int len;
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);//先保证有序
this.nums = nums;this.len = nums.length;
List<Integer> records = new ArrayList<Integer>();//保存当前子集
backTracking(false,records,0);
return ans;
}
//其中isPreChoose表示前一个元素是否选择加入集合,start是records的下标
public void backTracking(boolean isPreChoose,List<Integer> records,int start){
if(start == len) {//如果当前子集枚举完成就保存
ans.add(new ArrayList<Integer>(records));
}else{
backTracking(false,records,start+1);//不选择当前元素进入集合
//如果前一个元素没有被选中,并且当前元素确实有前一个元素时
//如果当前元素和前一个元素一样,就会产生重复的集合。直接return.
if(isPreChoose == false && start>0 && nums[start-1] == nums[start]) return;
//选择当前元素进入集合
records.add(nums[start]);
backTracking(true,records,start+1);
//不要忘了枚举后,将其去除,不要影响下一个子集的枚举
records.remove(records.size()-1);
}
}
}