Generate All Permutations: Backtracking with Swap

Sanjeev SharmaSanjeev Sharma
2 min read

Advertisement

Generate All Permutations

Approach 1: Used Array

def permute(nums):
    result = []
    used = [False] * len(nums)
    def bt(current):
        if len(current) == len(nums):
            result.append(current[:])
            return
        for i in range(len(nums)):
            if used[i]: continue
            used[i] = True
            current.append(nums[i])
            bt(current)
            current.pop()
            used[i] = False
    bt([])
    return result

# Permutations II (with duplicates)
def permuteUnique(nums):
    nums.sort()
    result = []
    used = [False] * len(nums)
    def bt(current):
        if len(current) == len(nums):
            result.append(current[:])
            return
        for i in range(len(nums)):
            if used[i]: continue
            # Skip: same value as previous, and previous was NOT used
            # (previous was used in a different branch, this creates duplicate)
            if i > 0 and nums[i] == nums[i-1] and not used[i-1]:
                continue
            used[i] = True
            current.append(nums[i])
            bt(current)
            current.pop()
            used[i] = False
    bt([])
    return result

Approach 2: In-Place Swap

def permute_swap(nums):
    result = []
    def bt(start):
        if start == len(nums):
            result.append(nums[:])
            return
        for i in range(start, len(nums)):
            nums[start], nums[i] = nums[i], nums[start]
            bt(start + 1)
            nums[start], nums[i] = nums[i], nums[start]
    bt(0)
    return result

C++ Implementation

#include <bits/stdc++.h>
using namespace std;

vector<vector<int>> permute(vector<int>& nums) {
    vector<vector<int>> result;
    sort(nums.begin(), nums.end());
    do {
        result.push_back(nums);
    } while (next_permutation(nums.begin(), nums.end()));
    return result;
}

// Manual backtracking
vector<vector<int>> permuteManual(vector<int> nums) {
    vector<vector<int>> result;
    function<void(int)> bt = [&](int start) {
        if (start == (int)nums.size()) {
            result.push_back(nums);
            return;
        }
        for (int i = start; i < (int)nums.size(); i++) {
            swap(nums[start], nums[i]);
            bt(start + 1);
            swap(nums[start], nums[i]);
        }
    };
    bt(0);
    return result;
}

Java Implementation

import java.util.*;

public class Permutations {
    public List<List<Integer>> permute(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        backtrack(nums, new boolean[nums.length], new ArrayList<>(), result);
        return result;
    }

    void backtrack(int[] nums, boolean[] used, List<Integer> curr, List<List<Integer>> result) {
        if (curr.size() == nums.length) {
            result.add(new ArrayList<>(curr));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (used[i]) continue;
            used[i] = true;
            curr.add(nums[i]);
            backtrack(nums, used, curr, result);
            curr.remove(curr.size() - 1);
            used[i] = false;
        }
    }
}

Complexity

  • Time: O(n! * n) — n! permutations, O(n) to copy each
  • Space: O(n) recursion depth

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro