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); } }
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注个人微信公众号!将会不按期的发放福利哦~微信