题目描述
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
题目解析
这类题目是典型的回溯算法,通过剪枝消除重复的子集。
以(1,2,2)为例:
代码模板一般是:
private void dfs(args...){
//因为回溯算法就是典型的递归操作,必须有终止条件
if(...){
return;
}
for(int i = ..;i < length;i++){
if(...){
//剪枝操作
...
continue;
}
//核心操作
add(..);
dfs(args...);
//撤销操作
remove(..);
}
}
代码实现
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
list.add(new ArrayList<>());
for (int i = 0; i < nums.length; i++) {
if (i != 0 && nums[i] == nums[i - 1]) {
continue;
}
Queue<Integer> queue = new ArrayDeque<>();
queue.add(nums[i]);
dfs(list, nums, i, queue);
}
return list;
}
private void dfs(List<List<Integer>> list, int[] nums, int index, Queue<Integer> queue) {
list.add(new ArrayList<>(queue));
for (int i = ++index; i < nums.length; i++) {
if (i != index && nums[i] == nums[i - 1]) {
continue;
}
queue.add(nums[i]);
dfs(list, nums, i, queue);
queue.remove(nums[i]);
}
}
性能分析
排序时间复杂度 O(nlogn),爆搜复杂度为 ( 2 n ) (2^n) (2n) 深拷贝存入答案,复杂度为 O(n)。整体复杂度为 ( n ∗ 2 n ) (n * 2^n) (n∗2n)
有不足之处多多指教
公众号:“计算机基础爱好者”