we can use the previous candidates that are not used at this level
[]
[1]
/ \
[1,2] [1, 3]
/ \!!! we can still add 2 here (not in subsets)
[1,2,3] [1, 3, 2]
Think of it we are doing a bfs at each level [1, ?]
Approach
The way it exhausts the search space is slightly different than combinations. Since the order does not matter, we can reuse elements that are smaller than the current element.
For example, given input [1, 2, 2], we have 2!1!3! permutations (with repetition). We are eliminating 3 cases where the second '2' is swapped with the first '2'. We want [1,21,22] instead of [1,22,21]. Therefore, once the input is sorted, we need to skip the current element when it is the same as the previous element and the previous element is not used.
1 Define recursion
generate all possible permutations with elements that are not inPerm
genPerms(List<List<Integer>> results, int[] nums, List<Integer> perm, boolean[] inPerm)
2 Recursive calls
for each element not inPerm
perm.add(ele)
inPerm[ele] = true
genPerms(results, nums, perm, inPerm)
3 Base case
if (perm.size() == nums.length)
results.add(new Perm)
return
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> results = new ArrayList<>();
// edge check
if (nums == null) return results;
// kick off helper
List<Integer> perm = new ArrayList<>();
boolean[] inPerm = new boolean[nums.length];
genPerms(results, nums, perm, inPerm);
return results;
}
private void genPerms(List<List<Integer>> results,
int[] nums,
List<Integer> perm,
boolean[] inPerm) {
// base case
if (perm.size() == nums.length) {
results.add(new ArrayList<>(perm));
return;
}
// recursive calls
for (int i = 0; i < nums.length; i++) {
if (inPerm[i]) continue;
perm.add(nums[i]);
inPerm[i] = true;
genPerms(results, nums, perm, inPerm);
perm.remove(perm.size() - 1);
inPerm[i] = false;
}
}
if (i != 0 && nums[i-1] == nums[i] && !used[i-1]) continue;