LeetCode 90. Subsets II (子集合之二)

Given a collection of integers that might contain duplicates, nums, return all possible subsets.

Note: The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,2], a solution is:

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

 


题目标签:Array

  题外话:搬完家后终于又回来刷题了,这次搬家整整用了2个星期,毕竟是从东北直接搬来了中南,光是开车就开了4天,每天开7小时,一共28小时。。。可是够累的。再加上各种杂事,看房租房,买家具,安装网络,换车牌。总算是差不多全搞定了,为了找一份工作也是不容易,那么回到刷题。

 

  这道题目和78. subset 方法二基本一样,只是多加了一个条件来防止duplicates subsets。那么如何防止duplicates subsets呢,我们来看原题例子 [1,2,2], 利用78. subset 的方法二, 我们可以得到 [ [ ], [1], [1,2], [1,2,2], [1,2], [2], [2,2], [2] ],其中有2个重复的子集合,[1,2] 和 [2]。根据方法二的code,我们可以发现,第二个 [1,2] 是在 for(int i=1; i<nums.length; i++)  这里面产生的。当 [1, 2, 2] 结束之后,remove 最后一个数字 变成 [1, 2],然后这个[1, 2]的 for loop 也结束了,返回后删除最后一个数字,变为 [1], 接着 for loop继续,移动到第二个2, 组成 [1,2] 产生的 重复子集合。 同样的,第二个 [2] 是在 for(int i=0; i<nums.length; i++) 这里面产生的, 当 [2, 2] 结束之后,删除最后一个数字变为[2],返回之后又删除最后一个数字变为 [ ], 然后for loop 继续移动到第二个2, 变为 [2] 产生的重复子集合。

  所以,重复的子集合都是在for loop里产生的,而且都是在第二个重复的数字那里。所以只需要多加一个条件 - 当遇到第二个重复的数字,直接跳过, 这样就可以在for loop 里避免重复的子集合。具体看code。

 

Java Solution:

Runtime beats 63.22% 

完成日期:08/25/2017

关键词:Array

关键点:递归, 跳过第二个重复的数字来避免重复子集合

 

 1 public class Solution 
 2 {
 3     public List<List<Integer>> subsetsWithDup(int[] nums) 
 4     {
 5         // sort nums array
 6         Arrays.sort(nums);
 7         // create res
 8         List<List<Integer>> res = new ArrayList<>();
 9         // call recursion function
10         helper(res, new ArrayList<>(), 0, nums);
11         
12         return res;
13     }
14     
15     public static void helper(List<List<Integer>> res, List<Integer> tmpRes, int pos, int[] nums)
16     {
17         // here should be <= not just < because we need to add the new tmpRes in next recursion.
18         // Therefore, we need one more bound to add tmpRes
19         if(pos <= nums.length)
20             res.add(new ArrayList<>(tmpRes));
21         
22         // once the new recursion is finished, remove the last number in the tmpRes and continue to 
23         // add rest numbers to get new subsets
24         for(int i=pos; i<nums.length; i++)
25         {
26             if(i > pos && nums[i] == nums[i-1]) // avoid duplicates
27                 continue;
28             
29             tmpRes.add(nums[i]);
30             helper(res, tmpRes, i+1, nums);
31             tmpRes.remove(tmpRes.size()-1);
32         }
33     }
34 }

参考资料:

https://discuss.leetcode.com/topic/22638/very-simple-and-fast-java-solution/4

 

 

LeetCode 算法题目列表 - LeetCode Algorithms Questions List

 

posted @ 2017-08-26 07:58  Jimmy_Cheng  阅读(271)  评论(0编辑  收藏  举报