1. 程式人生 > >LeetCode 90. Subsets II (子集合之二)

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

blank public fun res 東北 cau 利用 租房 .so

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

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