Problem

Given an integer n, return all possible permutations of the numbers from 1 to n (inclusive).

Example 1:

1
2
Input: n = 3
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

Solution

Intuition

This is the classic permutations problem. We can use backtracking to generate all possible orderings of the numbers 1 to n.

Approach

Use a recursive backtracking function that builds up a permutation by adding unused numbers at each step. When the permutation is complete (length n), add it to the result.

Code

C++
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
using namespace std;
class Solution {
public:
    vector<vector<int>> permute(int n) {
        vector<vector<int>> res;
        vector<int> path, used(n+1, 0);
        function<void()> dfs = [&]() {
            if (path.size() == n) { res.push_back(path); return; }
            for (int i = 1; i <= n; ++i) {
                if (used[i]) continue;
                used[i] = 1; path.push_back(i);
                dfs();
                path.pop_back(); used[i] = 0;
            }
        };
        dfs();
        return res;
    }
};
Go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func permute(n int) [][]int {
    var res [][]int
    var path []int
    used := make([]bool, n+1)
    var dfs func()
    dfs = func() {
        if len(path) == n {
            tmp := make([]int, n)
            copy(tmp, path)
            res = append(res, tmp)
            return
        }
        for i := 1; i <= n; i++ {
            if used[i] { continue }
            used[i] = true
            path = append(path, i)
            dfs()
            path = path[:len(path)-1]
            used[i] = false
        }
    }
    dfs()
    return res
}
Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.util.*;
class Solution {
    public List<List<Integer>> permute(int n) {
        List<List<Integer>> res = new ArrayList<>();
        List<Integer> path = new ArrayList<>();
        boolean[] used = new boolean[n+1];
        dfs(n, path, used, res);
        return res;
    }
    private void dfs(int n, List<Integer> path, boolean[] used, List<List<Integer>> res) {
        if (path.size() == n) {
            res.add(new ArrayList<>(path));
            return;
        }
        for (int i = 1; i <= n; i++) {
            if (used[i]) continue;
            used[i] = true; path.add(i);
            dfs(n, path, used, res);
            path.remove(path.size()-1); used[i] = false;
        }
    }
}
Kotlin
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution {
    fun permute(n: Int): List<List<Int>> {
        val res = mutableListOf<List<Int>>()
        val path = mutableListOf<Int>()
        val used = BooleanArray(n+1)
        fun dfs() {
            if (path.size == n) {
                res.add(path.toList())
                return
            }
            for (i in 1..n) {
                if (used[i]) continue
                used[i] = true
                path.add(i)
                dfs()
                path.removeAt(path.size-1)
                used[i] = false
            }
        }
        dfs()
        return res
    }
}
Python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def permute(n: int) -> list[list[int]]:
    res = []
    path = []
    used = [False] * (n+1)
    def dfs():
        if len(path) == n:
            res.append(path[:])
            return
        for i in range(1, n+1):
            if used[i]: continue
            used[i] = True
            path.append(i)
            dfs()
            path.pop()
            used[i] = False
    dfs()
    return res
Rust
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
fn permute(n: usize) -> Vec<Vec<usize>> {
    fn dfs(n: usize, path: &mut Vec<usize>, used: &mut Vec<bool>, res: &mut Vec<Vec<usize>>) {
        if path.len() == n {
            res.push(path.clone());
            return;
        }
        for i in 1..=n {
            if used[i] { continue; }
            used[i] = true;
            path.push(i);
            dfs(n, path, used, res);
            path.pop();
            used[i] = false;
        }
    }
    let mut res = vec![];
    let mut path = vec![];
    let mut used = vec![false; n+1];
    dfs(n, &mut path, &mut used, &mut res);
    res
}
TypeScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
function permute(n: number): number[][] {
    const res: number[][] = [];
    const path: number[] = [];
    const used = Array(n+1).fill(false);
    function dfs() {
        if (path.length === n) {
            res.push([...path]);
            return;
        }
        for (let i = 1; i <= n; i++) {
            if (used[i]) continue;
            used[i] = true;
            path.push(i);
            dfs();
            path.pop();
            used[i] = false;
        }
    }
    dfs();
    return res;
}

Complexity

  • ⏰ Time complexity: O(n!) (there are n! permutations, each takes O(n) to build)
  • 🧺 Space complexity: O(n!) (for storing all permutations)