1. Topic
地址: https://leetcode.com/problems/subsets-ii/
Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
Example:
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
2. DFS backtracking solution
Analytical thinking:
- To sort an array
- When the length of the list is less than or equal array length, when added to the result list
- If the current element with the same elements, is ignored.
package backtracking;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// https://leetcode.com/problems/subsets-ii/
public class SubsetsII {
public static void main(String[] args) {
int[] nums = {1,2,2};
SubsetsII obj = new SubsetsII();
List<List<Integer>> resultList = obj.subsetsWithDup(nums);
System.out.println(Arrays.toString(resultList.toArray()));
}
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> resultList = new ArrayList<List<Integer>>();
// dfs
dfs(nums, resultList, new ArrayList<Integer>(), 0);
return resultList;
}
private void dfs(int[] nums, List<List<Integer>> resultList, List<Integer> list, int start) {
if (start <= nums.length) {
resultList.add(list);
}
int i = start;
while (i < nums.length) {
list.add(nums[i]);
dfs(nums, resultList, new ArrayList<Integer>(list), i + 1);
list.remove(list.size() - 1);
i++;
while (i < nums.length && nums[i] == nums[i - 1]) {
i++;
}
}
}
}
3. Method circulation for backtracking
Problem-solving ideas with the same as above, to re-judge sentences if (i > start && nums[i] == nums[i - 1]) continue;
the more common inside backtracking algorithm, so it is in this way can also be solved.
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> resultList = new ArrayList<List<Integer>>();
// dfs
dfsWithFor(nums, resultList, new ArrayList<Integer>(), 0);
//subsetsWithDupHelper(nums, resultList, new ArrayList<Integer>(), 0);
return resultList;
}
private void dfsWithFor(int[] nums, List<List<Integer>> resultList, List<Integer> list, int start) {
// exit
if (start <= nums.length) {
resultList.add(new ArrayList<>(list));
}
for (int i = start; i < nums.length; i++) {
// duplicate case
if (i > start && nums[i] == nums[i - 1]) {
continue;
}
// pick up
list.add(nums[i]);
dfsWithFor(nums, resultList, list, i + 1);
// not pick up
list.remove(list.size() - 1);
}
}
4. The order of execution
Problem-solving ideas:
- Array nums ascending order
- One by one through the array nums elements
- If the current element and the last element is not the same, from the zero position to the existing list of results resultList traverse, the current element
nums[i]
will be added to the child list. - If the current element and the last element of the same size from the start on the back of the results list, this way you can filter out the same elements.
public List<List<Integer>> subsetsWithDupIterate(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> resultList = new ArrayList<List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
resultList.add(list);
int duplicateStart = 0;
for (int i = 0; i < nums.length; i++) {
int begin = 0;
int size = resultList.size();
if (i > 0 && nums[i] == nums[i - 1]) {
begin = duplicateStart;
}
for (int k = begin; k < size; k++) {
List<Integer> newList = new ArrayList<Integer>(resultList.get(k));
newList.add(nums[i]);
resultList.add(newList);
}
duplicateStart = size;
}
return resultList;
}