[LeetCode#47]Permutations II
2015-08-22 04:15
288 查看
Problem:
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
Analysis:
Solution 1:
Improvement:
Solution 2:
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].
Analysis:
This problem is very very typical to caculate permutation!!! It involves many coding skills as combination problem. But it also possess some distinct characteristics to to distinguish itself out. Basic idea: At each state(position), we search out every possible routines. Some routinies should be avoided during the explore process. case 1: The element has already been used. case 2: A element with the same value as other elements has already been placed at this position. Only one of them could be placed at this position, to avoid duplicates in the result set. Skill: 1.a use a boolean array to record if a element has already been used. boolean[] used = new boolean[nums.length]; 1.b sort the nums array, to avoid duplicates by taking advantage of sorted form. Note: since we need to permutate the array, rearrange the elements' order would not affect final result. Arrays.sort(nums); Unlike in the combination problem, we start from a passed in index. for (int i = start; i < nums.length; i++) In this problem, the start has no meaning. we would try to place each elements into the current pos(position), and use some checking codition to avoid duplicates and replacement. for (int i = 0; i < nums.length; i++) { ... } ************************************************* The skill in avoid duplicate is quite tricky!!! ************************************************ case 1: 2, 1, 1 case 2: 2, 1(1), 1 Apparently, we should have right mechanism to distinguish the above two cases. Principle: to avoid duplicate, at each position, if several availabel elements(has not been used) share the same value, we always place the first element at that position only! if (i > 0 && !used[i-1] && nums[i-1] == nums[i]) continue; a. firstly, we should guarantee the current element is not the first element, which has no previous element. b. secondly, we should make sure the nums[i-1] has no be used. Cause even "nums[i-1] == nums[i]", but it has already been used in the previous position. We don't need to take it into consideration. if (!used[i]) { .... } This can guarantee it would never be used for the current position. Note: There is no obvious 'cut-off' for base case, we avoid the search along wrong direction at for (int i = 0; i < nums.length; i++) { if (i > 0 && !used[i-1] && nums[i-1] == nums[i]) continue; ... helper(pos+1, nums, used, ret, path); ... } Thus when we reach "pos == nums.length", it means we get a right solution. The logic design is the same as "N-Quuens" problem. private void helper(int row, int n, int[] column_for_row, ArrayList<Integer> ret) { if (row == n) { ret.set(0, ret.get(0) + 1); return; } //a totally different way of thinking!!!! for (int i = 0; i < n; i++) { column_for_row[row] = i; if (isValid(row, column_for_row)) helper(row + 1, n, column_for_row, ret); } }
Solution 1:
public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> ret = new ArrayList<List<Integer>> (); if (nums == null || nums.length == 0) return ret; ArrayList<Integer> path = new ArrayList<Integer> (); boolean[] used = new boolean[nums.length]; Arrays.sort(nums); helper(0, nums, used, ret, path); return ret; } private void helper(int pos, int[] nums, boolean[] used, List<List<Integer>> ret, ArrayList<Integer> path) { if (pos == nums.length) { ret.add(new ArrayList<Integer> (path)); return; } for (int i = 0; i < nums.length; i++) { if (i > 0 && !used[i-1] && nums[i-1] == nums[i]) continue; if (!used[i]) { used[i] = true; path.add(nums[i]); helper(pos+1, nums, used, ret, path); path.remove(path.size()-1); used[i] = false; } } } }
Improvement:
Actually, for this problem, we could get the position information from the number of items in path. But the update would run more slower than directly pass around the position information. Thus the code could be changed into:
Solution 2:
public class Solution { public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> ret = new ArrayList<List<Integer>> (); if (nums == null || nums.length == 0) return ret; ArrayList<Integer> path = new ArrayList<Integer> (); boolean[] used = new boolean[nums.length]; Arrays.sort(nums); helper(nums, used, ret, path); return ret; } private void helper(int[] nums, boolean[] used, List<List<Integer>> ret, ArrayList<Integer> path) { if (path.size() == nums.length) { ret.add(new ArrayList<Integer> (path)); return; } for (int i = 0; i < nums.length; i++) { if (i > 0 && !used[i-1] && nums[i-1] == nums[i]) continue; if (!used[i]) { used[i] = true; path.add(nums[i]); helper(nums, used, ret, path); path.remove(path.size()-1); used[i] = false; } } } }
相关文章推荐
- shell脚本中一些特殊符号
- 使用wget 命令下载JDK的方法
- 操作队列
- XPath入门教程
- NGUI的代码控制
- 跳台阶解析【剑指Offer】
- uva11992区间修改线段树
- Mybatis 中 if test字符串比较问题
- android 比较靠谱的图片压缩
- mybatis动态SQL语句
- Mybatis的if test字符串比较问题
- node + Express 服务器性能实验
- XPath 多条件查询语句
- iOS链式编程框架介绍之LinkBlock(iOS链式编程)
- Ambari在线repo安装
- 正则表达式编程实例
- MyBatis参数传入集合之foreach动态sql
- Ambari离线安装
- MR案例:外连接代码实现
- MyBatis的动态SQL详解