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].Understand the problem:
The problem is an extension to Permutation I, the mainly difference is it exists the duplicated elements, and we return only unique permutations.
Solution:
The solution is very similar to the permutation I, the only difference is before we swap the number start and i, we check if between start and i has duplicates. If yes, it indicates that we visited the number before, so simply jump to next iteration.
Code (Java):
public class Solution {
public ArrayList<ArrayList<Integer>> permuteUnique(int[] num) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
permuteUnique(num, 0, result);
return result;
}
private void permuteUnique(int[] num, int start, ArrayList<ArrayList<Integer>> result) {
if (start >= num.length) {
ArrayList<Integer> temp = toArrayList(num);
result.add(temp);
return;
}
for (int i = start; i < num.length; i++) {
if (!containsDup(num, start, i)) {
swap(num, i, start);
permuteUnique(num, start + 1, result);
swap(num, i, start);
}
}
}
private void swap(int[] num, int i, int j) {
int temp = num[i];
num[i] = num[j];
num[j] = temp;
}
private ArrayList<Integer> toArrayList(int[] num) {
ArrayList<Integer> temp = new ArrayList<Integer>(num.length);
for (int i = 0; i < num.length; i++) {
temp.add(num[i]);
}
return temp;
}
private boolean containsDup(int[] num, int start, int end) {
for (int i = start; i <= end - 1; i++) {
if (num[i] == num[end]) return true;
}
return false;
}
}
Discussion:
Note the method on how to determine the duplicates. This the most tricky part of this problem.
Update on 07/29/18:
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
if (nums == null || nums.length == 0) {
return ans;
}
Arrays.sort(nums);
permuteHelper(0, nums, ans);
return ans;
}
private void permuteHelper(int start, int[] nums, List<List<Integer>> ans) {
if (start >= nums.length) {
ans.add(new ArrayList<>(Arrays.stream(nums).boxed().collect(Collectors.toList())));
return;
}
Set<Integer> set = new HashSet<>();
for (int i = start; i < nums.length; i++) {
if (set.add(nums[i])) {
swap(nums, i, start);
permuteHelper(start + 1, nums, ans);
swap(nums, i, start);
}
}
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
Update 5/7/19:
public class Solution {
/*
* @param : A list of integers
* @return: A list of unique permutations
*/
public List<List<Integer>> permuteUnique(int[] nums) {
// write your code here
List<List<Integer>> ans = new ArrayList<>();
if (nums == null || nums.length == 0) {
ans.add(new ArrayList<Integer>());
return ans;
}
Arrays.sort(nums);
boolean[] visited = new boolean[nums.length];
permuteUniqueHelper(nums, visited, new ArrayList<Integer>(), ans);
return ans;
}
private void permuteUniqueHelper(int[] nums, boolean[] visited, List<Integer> curList, List<List<Integer>> ans) {
if (curList.size() == nums.length) {
ans.add(new ArrayList<>(curList));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i]) {
continue;
}
if (i != 0 && nums[i] == nums[i - 1] && !visited[i - 1]) {
continue;
}
visited[i] = true;
curList.add(nums[i]);
permuteUniqueHelper(nums, visited, curList, ans);
visited[i] = false;
curList.remove(curList.size() - 1);
}
}
}
No comments:
Post a Comment