Leetcode47 Permutations II
2015-08-08 01:41
316 查看
Permutations II
Given a collection of numbers that might contain duplicates, return all possible unique permutations.For example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1].
Solution1
回溯法解决,但是要注意本轮循环要跳过已经使用过的重复的数字。import java.util.List; import java.util.ArrayList; import java.util.HashSet; public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> result = new ArrayList<List<Integer>>(); if(nums.length==0) return result; List<Integer> temp = new ArrayList<Integer>(); HashSet<Integer> used = new HashSet<Integer>(); help(nums,used,temp,result); return result; } public void help(int[] nums,HashSet<Integer> used,List<Integer>temp,List<List<Integer>>result){ if(temp.size()==nums.length){ result.add(temp); return; } HashSet<Integer> duplicate = new HashSet<Integer>(); for(int i=0;i<nums.length;i++){ if(used.contains(i)) continue;//如果这个位置上的数已经被用过了,则往下再搜寻 if(duplicate.contains(nums[i])) continue;//重复的数,在本次位置上不能再使用 HashSet<Integer> usedTemp = new HashSet<Integer>(used); usedTemp.add(i);//这里是存储下标 duplicate.add(nums[i]);//这里是存储数值 List<Integer> temp1 = new ArrayList<Integer>(temp); temp1.add(nums[i]); help(nums,usedTemp,temp1,result); } } }
Solution2
另一种类型的回溯。public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> result = new ArrayList<List<Integer>>(); //Arrays.sort(nums); permuteUnique2(nums,0,result); return result; } public void permuteUnique2(int[] nums,int start,List<List<Integer>> result){ if(start>=nums.length){ List<Integer> item = new ArrayList<Integer>(); for(int num:nums) item.add(num); result.add(item); return; } HashSet<Integer> used = new HashSet<Integer>(); for(int i=start;i<nums.length;i++){ if(used.contains(nums[i])) continue; int temp = nums[i]; nums[i] = nums[start]; nums[start] = temp; used.add(nums[start]); permuteUnique2(nums,start+1,result); nums[start] = nums[i]; nums[i] = temp; } } }
Solution3
和Leetcode46 Permutations中的解法4一样,这里仍然可以用插入法来求解,但是要复杂得多。这里插入数的时候不是以单个数为单位,而是以所有重复的数字为单位。public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> result = new ArrayList<List<Integer>>(); result.add(new ArrayList<Integer>()); Arrays.sort(nums); for(int i=0;i<nums.length;i++){ int count = 1; for(;i+1<nums.length&&nums[i+1]==nums[i];i++,count++);//统计重复的数字个数 int size = result.size(); for(int j=0;j<size;j++) insert(result.get(j),count,nums[i],result); while(size-->0) result.remove(0); } return result; } public void insert(List<Integer> item,int count,int num,List<List<Integer>> result){//将重复的数字插入已有的结果中 Stack<Integer> stack = new Stack<Integer>(); while(true){ for(int index=stack.empty()?0:stack.peek()+1;count>0;index++,count--){//插入 stack.push(index); item.add(index,num); } result.add(new ArrayList<Integer>(item)); int i = stack.pop(); item.remove(i); count++; for(;i==item.size();count++){//回溯 if(stack.empty()) return; i = stack.pop(); item.remove(i); } stack.push(i+1);//回溯成功后往后挪一个位置再插入 item.add(i+1,num); count--; } } }
思路较复杂,不推荐此算法。
Solution4
这里借鉴 Leetcode31 Next Permutation的思路来求解本题。public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> result = new ArrayList<List<Integer>>(); Arrays.sort(nums); while(true){ List<Integer> item = new ArrayList<Integer>(); for(int num:nums) item.add(num); result.add(item); int i,j; for(i=nums.length-1;i>0;i--) if(nums[i-1]<nums[i]) break; if(i<=0) break; for(j=nums.length-1;j>0;j--) if(nums[j]>nums[i-1]) break; int temp = nums[j]; nums[j] = nums[i-1]; nums[i-1] = temp; for(j = nums.length-1;i<j;i++,j--){ temp = nums[j]; nums[j] = nums[i]; nums[i] = temp; } } return result; } }
思路清晰易懂,并且还复用性还非常高。不管是有重复数字还是没有重复数字都可以用这种方法求解。所以比回溯法更值得推荐。
相关文章推荐
- leetcode 179 Largest Number
- leetcode 24 Swap Nodes in Pairs
- leetcode 2 Add Two Numbers 方法1
- leetcode 2 Add Two Numbers 方法2
- [LeetCode]47 Permutations II
- [LeetCode]65 Valid Number
- [LeetCode]123 Best Time to Buy and Sell Stock III
- [LeetCode] String Reorder Distance Apart
- [LeetCode] Sliding Window Maximum
- [LeetCode] Find the k-th Smallest Element in the Union of Two Sorted Arrays
- [LeetCode] Determine If Two Rectangles Overlap
- [LeetCode] A Distance Maximizing Problem
- leetcode_linearList
- leetcode_linearList02
- LeetCode[Day 1] Two Sum 题解
- LeetCode[Day 2] Median of Two Sorted Arrays 题解
- LeetCode[Day 3] Longest Substring Without... 题解
- LeetCode [Day 4] Add Two Numbers 题解
- LeetCode [Day 5] Longest Palindromic Substring 题解
- LeetCode [Day 6] ZigZag Conversion 题解