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].
Java Solution 1
Based on Permutation, we can add a set to track if an element is duplicate and no need to swap.
public List<List<Integer>> permuteUnique(int[] nums) { List<List<Integer>> result = new ArrayList<>(); helper(0, nums, result); return result; } private void helper(int start, int[] nums, List<List<Integer>> result){ if(start==nums.length-1){ ArrayList<Integer> list = new ArrayList<>(); for(int num: nums){ list.add(num); } result.add(list); return; } HashSet<Integer> set = new HashSet<>(); for(int i=start; i<nums.length; i++){ if(set.contains(nums[i])){ continue; } set.add(nums[i]); swap(nums, i, start); helper(start+1, nums, result); swap(nums, i, start); } } private void swap(int[] nums, int i, int j){ int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; } |
Java Solution 2
Use set to maintain uniqueness:
public static ArrayList<ArrayList<Integer>> permuteUnique(int[] num) { ArrayList<ArrayList<Integer>> returnList = new ArrayList<ArrayList<Integer>>(); returnList.add(new ArrayList<Integer>()); for (int i = 0; i < num.length; i++) { Set<ArrayList<Integer>> currentSet = new HashSet<ArrayList<Integer>>(); for (List<Integer> l : returnList) { for (int j = 0; j < l.size() + 1; j++) { l.add(j, num[i]); ArrayList<Integer> T = new ArrayList<Integer>(l); l.remove(j); currentSet.add(T); } } returnList = new ArrayList<ArrayList<Integer>>(currentSet); } return returnList; } |
Thanks to Milan for such a simple solution!
if(set.contains(nums[i])){
=====
not sure using set. what for?
basically you just need skip from forming similar string
lets say string 1xx 1 xxx 1 xxx , if you swap 1 and 1, you will make 2 same strings
so as soon as i-index and start-index same symbol, just skip next swap operation
contains duplicate == true is actually false in common sense. What a weird naming?
But if i want write in file, without printing?
Once you swap, the following numbers are not sorted anymore
Will take O(n!) space?
thanks for the solution. Would you mind to explain the containsDuplicate code?
private boolean containsDuplicate(int[] arr, int start, int end) {
for (int i = start; i <= end-1; i++) {
if (arr[i] == arr[end]) {
return false;
}
}
return true;
}
Why should we do that to avoid duplication.
You can swap the input and skip numbers that are duplicates.
import java.util.*;
public class PrintUniquePermutations {
public static void main(String args[]) {
int[] input = {1, 2, 1};
Arrays.sort(input);
String prefix = “”;
printUnique(prefix, input, 0);
}
private static void printUnique(String prefix, int[] input, int start) {
if (start == input.length) {
System.out.println(prefix);
return;
}
for (int i = start; i < input.length; i++) {
if (i != start && input[i] == input[i-1]) {
continue;
}
swap(input, i, start);
printUnique(prefix + ", " + String.valueOf(input[start]), input, start + 1);
swap(input, i, start);
}
}
private static void swap(int[] input, int i, int j) {
int tmp = input[i];
input[i] = input[j];
input[j] = tmp;
}
}
Thanks! Great solution!
Use set to maintain uniqueness:
List<List> returnList = new ArrayList<List> ();
returnList.add(new ArrayList());
for (int i=0 ; i < num.length; i++){
Set<List> currnetSet = new HashSet<List> ();
for (List l:returnList){
for(int j=0;j< l.size() +1;j++){
l.add(j,num[i]);
ArrayList T = new ArrayList(l);
l.remove(j);
currnetSet.add(T);
}
}
returnList = new ArrayList<List> (currnetSet);
}
return returnList;
}
应该是ä¸contain duplicate