LintCode 18. Subsets II 原创Java参考解答

LintCode 18. Subsets II 原创Java参考解答

问题描述

http://www.lintcode.com/en/problem/subsets/

Given a list of numbers that may has duplicate numbers, return all possible subsets

Notice
  • Each element in a subset must be in non-descending order.
  • The ordering between two subsets is free.
  • The solution set must not contain duplicate subsets.
Example

If S = [1,2,2], a solution is:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

解题思路

这道题是Subsets题目的Follow up加强版题目。求一个数组的所有子集数组。原数组可能有重复元素。

Subsets题目基本上一样的思路和解法,由题目“求所有子集”联想到DFS深度优先搜索。考点仍旧是递归,只是这道题需要去重。

我们不能求完所有子集后再去重,因为那样时间复杂度会太高,为O(2N * N),N为数组元素数量。我们需要在递归找子集过程中就处理重复的情况。

参考代码

解答代码和Subsets代码基本一样,只是加入了去重的手段。我们的去重手段就是对于相同的数字只用计算出前面一个的子集。比如,对于[1, 1],我们只用求出前面一个1的所有子集。

  • 排序数组使数值一样的元素相邻地排在一起
  • 如果某位置元素和前一位置数值相同了,即nums[i] = nums[i – 1],那么就跳过该位置。通过 i > startIndex 来判断当前 i 是否是当前子集的出发位置还是后面位置。
class Solution { 
    /** 
     * @param nums: A set of numbers. 
     * @return: A list of lists. All valid subsets. 
     */ 
    public ArrayList<ArrayList<Integer>> subsetsWithDup(int[] nums) { 
        ArrayList<ArrayList<Integer>> results = new ArrayList<ArrayList<Integer>>(); 
        if (nums == null || nums.length == 0) { 
            return results; 
        } 
         
        Arrays.sort(nums); 
        ArrayList<Integer> subset = new ArrayList<Integer>(); 
        dfsHelper(nums, 0, subset, results); 
        return results; 
    } 
     
    private void dfsHelper(int[] nums, int startIndex, ArrayList<Integer> subset, ArrayList<ArrayList<Integer>> results) { 
        // deep copy and add to results 
        results.add(new ArrayList<Integer>(subset)); 
         
        for (int i = startIndex; i < nums.length; i++) { 
            if (i != 0 && nums[i] == nums[i - 1] && i > startIndex) { 
                continue; 
            } 
            subset.add(nums[i]); 
            dfsHelper(nums, i + 1, subset, results); 
            subset.remove(subset.size() - 1); 
        } 
    } 
} 

相关题目

LintCode All in One 原创题目讲解汇总

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注