原题网址:https://leetcode.com/problems/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]
.
方法一:深度优先搜索,使用集合检查重复。
public class Solution {
private void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
private void dfs(int[] nums, int from, List<List<Integer>> results) {
if (from == nums.length) {
List<Integer> result = new ArrayList<Integer>();
for(int i=0; i<nums.length; i++) result.add(nums[i]);
results.add(result);
return;
}
Set<Integer> used = new HashSet<Integer>();
for(int i=from; i<nums.length; i++) {
if (used.contains(nums[i])) continue;
used.add(nums[i]);
swap(nums, from, i);
dfs(nums, from+1, results);
swap(nums, from, i);
}
}
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> results = new ArrayList<>();
if (nums == null || nums.length == 0) return results;
dfs(nums, 0, results);
return results;
}
}
方法二:运用循环右移、左移的方法,巧妙的避免使用used集合。
public class Solution {
private void swap(int[] nums, int i, int j) {
int t = nums[i];
nums[i] = nums[j];
nums[j] = t;
}
private void dfs(int[] nums, int from, List<List<Integer>> results) {
if (from == nums.length-1) {
Integer[] result = new Integer[nums.length];
for(int i=0; i<nums.length; i++) result[i] = nums[i];
results.add(Arrays.asList(result));
return;
}
// 循环一轮下来,nums[from..nums.length]相当于循环右移了一次。
for(int i=from; i<nums.length; i++) {
if (i>from && nums[i]==nums[from]) continue;
swap(nums, from, i);
dfs(nums, from+1, results);
}
// 循环左移回去
for(int i=nums.length-1; i>=from; i--) {
swap(nums, from, i);
}
}
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> results = new ArrayList<>();
if (nums == null || nums.length == 0) return results;
Arrays.sort(nums);
dfs(nums, 0, results);
return results;
}
}