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], [] ]
能夠先參考關於SubsetI
的這篇博客再看接下來的內容。
這裏的區別在於假設輸入的數組存在重複值,則找到全部不重複的子集。面試
咱們能夠經過例子[1,2,2,3]
來講明。當咱們遇到重複值時,咱們能夠使用一個臨時數組將全部重複值的結果臨時保存起來,在這道題目中就是[[2],[2,2]],而後再將當前res中的結果和它一一組合成新的結果值,本例子中的當前res爲[[ ],[1]],這樣合成以後就是[[],[2],[2,2],[1,2],[1,2,2]]
,從而避免產生重複的結果。
代碼以下:segmentfault
public List<List<Integer>> subsetsWithDup(int[] nums) { List<List<Integer>> result = new LinkedList<List<Integer>>(); result.add(new ArrayList<Integer>()); int length = nums.length; Arrays.sort(nums); for(int i = 0 ; i<length ; ){ LinkedList<List<Integer>> temp = new LinkedList<List<Integer>>(); for(List<Integer> tempResult : result){ List<Integer> copyTemp = new ArrayList<Integer>(tempResult); copyTemp.add(nums[i]); temp.add(copyTemp); } i++; while(i<length && nums[i]==nums[i-1]){ int size = temp.size(); while(size-->0){ List<Integer> currentTemp = temp.removeFirst(); result.add(currentTemp); List<Integer> moreCurrentTemp = new ArrayList<Integer>(currentTemp); moreCurrentTemp.add(nums[i]); temp.add(moreCurrentTemp); } } result.addAll(temp); } return result; }
其實對於遞歸,應當考慮從遞歸的輸入和輸出考慮。在這裏咱們將遞歸的輸入爲當前的結果集,當前的數組,和遍歷的起始下標。在遞歸中咱們會將起始下標後的值依次加入當前結果集,並將結果集加入結果集數組中。若是遇到重複的數字,則繼續遍歷下一個數字,直至遍歷結束。思路簡單清晰,效率也很高。數組
public List<List<Integer>> subsetsWithDup2(int[] nums) { List<List<Integer>> fnl = new ArrayList<List<Integer>>(); Arrays.sort(nums); helper(fnl, new ArrayList<Integer>(), nums, 0); return fnl; } public void helper(List<List<Integer>> fnl, List<Integer> temp, int[] nums, int start){ fnl.add(new ArrayList<Integer>(temp)); for(int i =start; i<nums.length; i++){ if(i>start && nums[i]==nums[i-1]) continue; temp.add(nums[i]); helper(fnl, temp, nums, i+1 ); temp.remove(temp.size()-1); } }
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~微信