首页 > 代码库 > 47. Permutations II ?
47. 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]
.
链接: http://leetcode.com/problems/permutations-ii/
4/15/2017
自己的做法是错的,但是按照别人的改一下就对了。
自己的错误做法,一直到[1,0,2,0,1,-1,-1]才有test case挂的情况,正确是有630个解,我的算法有696个解。
1 public class Solution { 2 public List<List<Integer>> permuteUnique(int[] nums) { 3 List<List<Integer>> ret = new ArrayList<>(); 4 if (nums.length == 0) return ret; 5 Arrays.sort(nums); 6 enumerate(nums, ret, 0); 7 return ret; 8 } 9 private void enumerate(int[] nums, List<List<Integer>> ret, int pos) { 10 if (pos == nums.length) { 11 ArrayList<Integer> list = new ArrayList<Integer>(); 12 for (int i = 0; i < nums.length; i++) { 13 list.add(nums[i]); 14 } 15 ret.add(list); 16 return; 17 } 18 for (int i = pos; i < nums.length; i++) { 19 if (i != pos && (nums[i] == nums[pos] || nums[i] == nums[i - 1])) continue; 20 exchange(nums, pos, i); 21 enumerate(nums, ret, pos + 1); 22 exchange(nums, i, pos); 23 } 24 } 25 private void exchange(int[] nums, int i, int j) { 26 int tmp = nums[i]; 27 nums[i] = nums[j]; 28 nums[j] = tmp; 29 } 30 }
按照讨论修改了几句,也不需要sort,10ms, 45%
https://discuss.leetcode.com/topic/36221/share-my-java-code-with-detailed-explanantion
我不能解释为什么会这样,不过我的猜想是即使最开始已经sort过了,在中间的各种交换之后也许不能保证在recursive function之内相同元素是相邻的了。
很多算法题有去重复的要求,有时候需要判断相邻元素,有时候要用set。什么情况用啥呢?
这道题让我意识到需要理解其他更普遍的backtracking permutation的算法
1 public class Solution { 2 public List<List<Integer>> permuteUnique(int[] nums) { 3 List<List<Integer>> ret = new ArrayList<>(); 4 if (nums.length == 0) return ret; 5 enumerate(nums, ret, 0); 6 return ret; 7 } 8 private void enumerate(int[] nums, List<List<Integer>> ret, int pos) { 9 if (pos == nums.length) { 10 ArrayList<Integer> list = new ArrayList<Integer>(); 11 for (int i = 0; i < nums.length; i++) { 12 list.add(nums[i]); 13 } 14 ret.add(list); 15 return; 16 } 17 Set<Integer> appeared = new HashSet<>(); 18 for (int i = pos; i < nums.length; i++) { 19 if (!appeared.add(nums[i])) continue; 20 exchange(nums, pos, i); 21 enumerate(nums, ret, pos + 1); 22 exchange(nums, i, pos); 23 } 24 } 25 private void exchange(int[] nums, int i, int j) { 26 int tmp = nums[i]; 27 nums[i] = nums[j]; 28 nums[j] = tmp; 29 } 30 }
Princeton Introduction to Programming in Java里对permutation有很多介绍,可惜没有跟这道题一样的。有机会一定看看:
http://introcs.cs.princeton.edu/java/23recursion/
别人的做法:
visited的意义?在当前层还是递归层?
1 public class Solution { 2 public List<List<Integer>> permuteUnique(int[] nums) { 3 List<List<Integer>> res = new ArrayList<>(); 4 if (nums == null || nums.length == 0) { 5 return res; 6 } 7 Arrays.sort(nums); 8 boolean[] visited = new boolean[nums.length]; 9 permuteUnique(res, new ArrayList<Integer>(), visited, nums); 10 return res; 11 } 12 13 private void permuteUnique(List<List<Integer>> res, List<Integer> onePerm, boolean[] visited, int[] nums) { 14 if (onePerm.size() == nums.length) { 15 res.add(new ArrayList<>(onePerm)); 16 return; 17 } 18 for (int i = 0; i < nums.length; i++) { 19 if (visited[i] || (i > 0 && nums[i] == nums[i - 1] && visited[i - 1])) { 20 continue; 21 } 22 visited[i] = true; 23 onePerm.add(nums[i]); 24 permuteUnique(res, onePerm, visited, nums); 25 onePerm.remove(onePerm.size() - 1); 26 visited[i] = false; 27 } 28 } 29 }
更多讨论:
https://discuss.leetcode.com/category/55/permutations-ii
47. Permutations II ?