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.
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
Code
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;
Follow Up Question ()
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.