1. 주제
地址: https://leetcode.com/problems/subsets-ii/
가능한 모든 부분 집합 (전원 설정), 중복, nums를 포함 반환 할 수 있습니다 정수의 집합을 감안할 때.
참고 :이 솔루션 세트는 중복 하위 집합을 포함 할 수 없습니다.
예:
Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]
솔루션을 되돌아 2. DFS
분석적 사고 :
- 배열을 정렬하려면
- 리스트의 길이가 같거나 배열 길이 이하이면, 결과리스트에 추가 될 때
- 같은 요소가 현재 요소 경우 무시됩니다.
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. 방법 순환
문제 해결 재 판단 문장을 상기와 같은 아이디어 if (i > start && nums[i] == nums[i - 1]) continue;
는도 해소 할 수있다이 방법하므로, 일반적인 인사이드 되돌아 알고리즘.
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. 실행 순서
문제 해결 아이디어 :
- 배열 nums 오름차순 순서
- 배열을 통해 하나씩 nums의 요소
- 현재 요소와 마지막 요소는 결과의 기존 목록에 제로 위치에서, 동일하지 않은 경우 resultList의 트래버스, 현재 요소는
nums[i]
자식 목록에 추가됩니다. - 만약 현재 요소 및 결과 목록의 뒷면에 처음부터 같은 크기의 마지막 요소, 같은 요소를 필터링 할 수 있습니다 이런 식으로.
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;
}