Permutations II
update Jul 21, 2017 21:04
LintCode Given a list of numbers with duplicate number in it. Find all unique permutations.
Example
For numbers [1,2,2] the unique permutations are:
[
[1,2,2],
[2,1,2],
[2,2,1]
]
Basic Idea:
每次考虑一位数,维持一个boolean[] used 数组,选过的数字设为true。另外要注意去重。
Java Code:
class Solution {
/**
* @param nums: A list of integers.
* @return: A list of unique permutations.
*/
public List<List<Integer>> permuteUnique(int[] nums) {
// Write your code here
List<List<Integer>> res = new ArrayList<>();
if (nums == null || nums.length == 0) {
res.add(new ArrayList<Integer>());
return res;
}
Arrays.sort(nums);
dfs(nums, new boolean[nums.length], 0, new ArrayList<Integer>(), res);
return res;
}
private void dfs(int[] nums, boolean[] used, int pos, List<Integer> path, List<List<Integer>> res) {
if (pos == nums.length) {
res.add(new ArrayList<Integer>(path));
return;
}
int prev = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; ++i) {
if (used[i] || nums[i] == prev) continue;
prev = nums[i];
used[i] = true;
path.add(nums[i]);
dfs(nums, used, pos + 1, path, res);
path.remove(path.size() - 1);
used[i] = false;
}
}
}
Python Code:
class Solution:
"""
@param nums: A list of integers.
@return: A list of unique permutations.
"""
def permuteUnique(self, nums):
if not nums:
return [[]]
nums.sort()
res = []
used = [False] * len(nums)
self.helper(nums, 0, used, [], res)
return res
def helper(self, nums, pos, used, path, res):
# int[] nums, int pos, boolean[] used, list<int> path, list<list<int>> res
if pos == len(nums):
res.append(path[:])
return
for i in range(len(nums)):
if used[i]: continue
if i != 0 and nums[i] == nums[i - 1] and not used[i - 1]: continue
path.append(nums[i])
used[i] = True
self.helper(nums, pos + 1, used, path, res)
used[i] = False
del path[-1]
update Jan 8,2017 12:24
Upate:使用 Swap-Swap 方法处理,降低了时间复杂度
参考前面的 《DFS notes》;
与普通permutation问题不同的地方就在于这里需要去重,我们只需要在每层循环中用一个 HashSet 记录当前已经选择过的 element 就可以了。
Python Code:
class Solution:
def permuteUnique(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
def dfs(nums, pos, res):
if pos == len(nums):
res.append(nums[:])
return
# 对每个候选数字,将其换到pos位,向后继续dfs,之后再换回来做backtracking
# 去重:因为换位之后先前的顺序会被打乱,我们只能每层维持一个HashSet记录已经选择过的element
used = set()
for i in range(pos, len(nums)):
if nums[i] in used: continue
used.add(nums[i])
swap(nums, pos, i)
dfs(nums, pos + 1, res)
swap(nums, pos, i)
def swap(nums, a, b):
t = nums[a]
nums[a] = nums[b]
nums[b] = t
res = []
if not nums: return res
dfs(nums, 0, res)
return res