Problem
Given an array nums
of distinct integers, return all the possible permutations. You can return the answer in any order.
OR
Given a collection of numbers, return all possible permutations.
Examples
Example 1:
nums = [1,2,3]
Output: [
[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]
]
NOTE: No two entries in the permutation sequence should be the same. For the purpose of this problem, assume that all the numbers in the collection are unique.
Warning : DO NOT USE LIBRARY FUNCTION FOR GENERATING PERMUTATIONS. Example : next_permutations in C++ / itertools.permutations in python. If you do, we will disqualify your submission retroactively and give you penalty points.
Follow up problem - Permutations II
Solution
Method 1 - Backtracking storing current permutation in List
Code
Java
Code with list only
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), nums);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> subAns, int [] nums){
if(tempList.size() == nums.length){
list.add(new ArrayList<>(subAns));
} else{
for(int i = 0; i < nums.length; i++){
if(subAns.contains(nums[i])) {
continue; // element already exists, skip
}
tempList.add(nums[i]);
backtrack(list, tempList, nums);
tempList.remove(tempList.size() - 1);
}
}
}
Method 2 - Using HashSet
Code
Java
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> ans = new ArrayList<>();
backtrack(ans, new ArrayList<>(), new HashSet<>(), nums);
return ret;
}
private void backtrack(List<List<Integer>> ans, List<Integer> subAns, Set<Integer> tmpSet, int[] nums) {
if (tmpSet.size() == nums.length) {
ans.add(new ArrayList<>(new ArrayList<>(tmpList)));
return;
}
for (int i = 0; i < nums.length; i++) {
if (tmpSet.contains(nums[i])) {
continue;
}
tmpSet.add(nums[i]);
subAns.add(nums[i]);
backtrack(ret, subAns, tmpSet, nums);
tmpSet.remove(subAns.get(tmpList.size()-1));
subAns.remove(subAns.size()-1);
}
}
Note we are using tmpSet
to complment subAns
list, as we need contains
operations, which is O(1)
for hashset, but O(n)
for list.
Approach 2 - Backtracking with Visited Array
A list to represent permutation constructed so far, path A list to record which letters are already used, used, visited[i] == true means ith letter in the origin list has been used.
public List<List<Integer>> permute(int[] nums) {
boolean[] visited = new boolean[nums.length];
List<List<Integer>> ans = new ArrayList<>();
helper(nums,visited,ans, new ArrayList<>());
return ans;
}
void helper(int[] nums, boolean[] visited, List<List<Integer>> ans, List<Integer> subAns) {
if (subAns.size() == nums.length){
ans.add(new ArrayList<>(subAns));
return;
}
for(int i=0;i<nums.length;i++){
if(visited[i]) {
continue;
}
subAns.add(nums[i]);
visited[i]=true;
helper(nums,visited,ans,subAns);
visited[i]=false;
subAns.remove(subAns.size()-1);
}
}
Note: It is very important to do:
ans.add(new ArrayList<>(subAns));
and not:
ans.add(subAns);
As, subAns is constantly modified. So, they will be become empty[] eventually, so we will get wrong answer. new ArrayList<>(subAns)
creates deep copy.
Method 2 - Backtracking with Swapping Elements in Array
We can follow following steps:
Step 0: Initialize the variables start
and end
with start = 0
and end = n - 1
. Call the method: permutations(array, start, end)
.
Step 1: Loop over the array from start
to end
using an index.
Step 2: Fix the character at the current index by swapping the character at start
with the character at the index.
Step 3: Recursively generate all permutations for the remaining positions by calling the method again with updated parameters: permutations(array, start + 1, end)
.
Step 4: Backtrack by swapping the character at start
back with the character at the index.
Try to dry run with n = 3 and nums = [1,2,3]
Code
Java
private void permutation(int[] nums, int start, int end, List<List<Integer> ans) {
if (start == end) {
ans.add(Arrays.stream(nums)
.boxed()
.collect(Collectors.toList()););
}
for (int i=start; i<= end; i++){
swap(nums, start, i);
permutation(nums, start+1, end);
swap(nums, start, i);
}
}
private int[] swap(int[] a, int i, int j) {
char temp = a[i];
a[i] = a[j];
a[j] = temp;
return a;
}
Complexity
The complexity of all solutions is:
- ⏰ Time complexity:
O(n*n!)
wheren
is number of elements in array - 🧺 Space complexity:
O(n!)
Why?