import java.util.*; /** * 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]. * * Tags: Backtracking */ class Permutations2 { public static void main(String[] args) { List<List<Integer>> res = permuteUniqueB(new int[]{1, 2, 3}); for (List<Integer> l : res) System.out.println(l); } /** * Same idea as Permutation 1 except we skip if duplicate of current element * is found in previous sequence */ public List<List<Integer>> permuteUnique(int[] num) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (num == null || num.length == 0) return res; Arrays.sort(num); permute(num, 0, res); return res; } public void permute(int[] num, int pos, List<List<Integer>> res) { if (pos == num.length) { List<Integer> row = new ArrayList<Integer>(); for (int a : num) row.add(a); res.add(row); return; } for (int i = pos; i < num.length; i++) { // skip if we have duplicates of current element before i boolean skip = false; for (int j = pos; j < i; j++) { if (num[j] == num[i]) { skip = true; break; } } if (skip) continue; swap(num, pos, i); permute(num, pos + 1, res); swap(num, pos, i); // reset } } public void swap(int[] num, int i, int j) { if (i == j) return; num[i] = num[j] - num[i]; num[j] = num[j] - num[i]; num[i] = num[j] + num[i]; } /** * Lexicography Order next permutation * Find the next permutation in lexicographic order. *http://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order */ public static List<List<Integer>> permuteUniqueB(int[] num) { List<List<Integer>> res = new ArrayList<List<Integer>>(); if (num == null || num.length == 0) return res; Arrays.sort(num); List<Integer> row = new ArrayList<Integer>(); for (int a : num) row.add(a); res.add(new ArrayList<Integer>(row)); // first permutation while (nextPermutation(row)) { // if there is next permutation res.add(new ArrayList<Integer>(row)); } return res; } /** * e.g.: 1234 -> 1243, 1243 -> 1324 * Traverse backward to get 3 * Then traverse forward to get furthest number bigger than 3 * Swap these two digits and reverse from next to last */ public static boolean nextPermutation(List<Integer> row) { int last = row.size() - 1; for (int pos = last - 1; pos >= 0; pos--) { if (row.get(pos) < row.get(pos + 1)) { int smallIdx = pos; int biggerIdx = pos + 1; for (int i = pos + 1; i <= last; i++) if (row.get(i) > row.get(pos)) biggerIdx = i; swap(row, smallIdx, biggerIdx); reverse(row, pos + 1, last); return true; } } return false; } public static void swap(List<Integer> row, int a, int b) { int t = row.get(a); row.set(a, row.get(b)); row.set(b, t); } public static void reverse(List<Integer> row, int s, int e) { while (s < e) { swap(row, s, e); s++; e--; } } }