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); } } }