[回溯法] -- 90 子集 -- Python + Java

159 阅读1分钟

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: [1,2,2]
输出:
[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

题目给定的数组中会包含重复的数字,如果简单的对数组求所有的排列,会发现结果集中的大小会超过正确结果集的大小。这是因为[1, 2][2,1 ]这里认为是相同的,因此在回溯过程中保存可能的结果是,需要对当前的结果进行排序然后判断结果集中是否存在排序后的结果:

  • 如果存在则继续回溯
  • 否则在结果集中添加排序后的结果

Python解题代码:

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
		sorted(nums)
        res = []
        def dfs(nums, track):
            if sorted(track) not in res:
                res.append(sorted(track).copy())
    
            for i in range(len(nums)):
                track.append(nums[i])
                dfs(nums[i + 1:], track)
                track.pop()

        dfs(nums, [])
        return res

Java解题代码:

class Solution {
    public List<List<Integer>> subsetsWithDup(int[] nums) {
        Arrays.sort(nums);

        List<List<Integer>> results = new LinkedList<>();
        LinkedList<Integer> track = new LinkedList<>();

        dfs(nums, track, results, 0);
        return results;
    }

    private void dfs(int[] nums, LinkedList<Integer> track, List<List<Integer>> results, int start) {
        Collections.sort(track);
        if(!results.contains(track)){
            results.add(new LinkedList<>(track));
        }

        for(int i = start; i < nums.length; i++){
            if (i != start && nums[i] == nums[i - 1]) 
                continue;
            track.add(nums[i]);
            dfs(nums, track, results, i + 1);
            track.removeLast();
        }

    }
}