알고리즘 : 서브 세트 II 다시 열세 겹치지 어레이의 서브 세트 (용액 세 종류)

1. 주제

地址: https://leetcode.com/problems/subsets-ii/
가능한 모든 부분 집합 (전원 설정), 중복, nums를 포함 반환 할 수 있습니다 정수의 집합을 감안할 때.

참고 :이 솔루션 세트는 중복 하위 집합을 포함 할 수 없습니다.

예:

Input: [1,2,2]
Output:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

솔루션을 되돌아 2. DFS

분석적 사고 :

  1. 배열을 정렬하려면
  2. 리스트의 길이가 같거나 배열 길이 이하이면, 결과리스트에 추가 될 때
  3. 같은 요소가 현재 요소 경우 무시됩니다.
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. 실행 순서

문제 해결 아이디어 :

  1. 배열 nums 오름차순 순서
  2. 배열을 통해 하나씩 nums의 요소
  3. 현재 요소와 마지막 요소는 결과의 기존 목록에 제로 위치에서, 동일하지 않은 경우 resultList의 트래버스, 현재 요소는 nums[i]자식 목록에 추가됩니다.
  4. 만약 현재 요소 및 결과 목록의 뒷면에 처음부터 같은 크기의 마지막 요소, 같은 요소를 필터링 할 수 있습니다 이런 식으로.
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;
}

다운로드

https://github.com/zgpeace/awesome-java-leetcode/blob/master/code/LeetCode/src/backtracking/SubsetsII.java

发布了127 篇原创文章 · 获赞 12 · 访问量 2万+

추천

출처blog.csdn.net/zgpeace/article/details/103922570