Alkesh

LeetCode - Permutations

Problem statement

Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.

Problem statement taken from: https://leetcode.com/problems/permutations

Example 1:

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

Example 2:

Input: nums = [0, 1]
Output: [[0, 1], [1, 0]]

Example 3:

Input: nums = [1]
Output: [[1]]

Constraints:

- 1 <= nums.length <= 6
- -10 <= nums[i] <= 10
- All the integers of nums are unique.

Explanation

Backtracking

Container

When we are required to generate a permutation or a sequence, recursion is the best approach to use. The recursion for this problem will be a bit different compared to the standard recursion approach.

One approach to solve this problem is to keep track of the element we have visited and generate permutations for the rest of the array elements. But, we can solve this by swapping the array elements.

Let's jump to the algorithm to understand it better.

- set result = [[]]

- call _getPermutations(result, nums, 0, nums.length - 1)

- return result

// _getPermutations(result, nums, l, r)
- if l == r
  - push the current nums permutation in the result
  - result.push(nums)
- else
  - loop for i = l; i <= r; i++
    - swap(nums[l], nums[i])

    - _getPermutations(result, nums, l + 1, r)

    - swap(nums[l], nums[i])
- end if

Let's check our algorithm in C++, Golang, and Javascript.

C++ solution

class Solution {
public:
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int>> result;

        _getPermutations(result, nums, 0, nums.size() - 1);
        return result;
    }

    void _getPermutations(vector<vector<int>>& result, vector<int> nums, int l, int r){
        if(l == r){
            result.push_back(nums);
            return;
        } else {
            for(int i = l; i <= r; i++){
                swap(nums[l], nums[i]);

                _getPermutations(result, nums, l + 1, r);

                swap(nums[l], nums[i]);
            }
        }
    }
};

Golang solution

func permute(nums []int) [][]int {
    result := [][]int{}

    _getPermutations(&result, nums, 0, len(nums) - 1)

    return result
}

func _getPermutations(result *[][]int, nums []int, l, r int) {
    if l == r {
        cp := make([]int, len(nums))
        copy(cp, nums)
        *result = append(*result, cp)
    } else {
        for i := l; i <= r; i++ {
            nums[l], nums[i] = nums[i], nums[l]

            _getPermutations(result, nums, l + 1, r)

            nums[l], nums[i] = nums[i], nums[l]
        }
    }
}

Javascript solution

var permute = function(nums) {
    const result = [];

    _getPermutations(result, nums, 0, nums.length - 1);

    return result;
};

function _getPermutations(result, nums, l, r) {
    if(l === r) {
        result.push(nums.slice(0));
        return;
    } else {
        for(let i = l; i <= r; i++) {
            [nums[l], nums[i]] = [nums[i], nums[l]];

            _getPermutations(result, nums, l + 1, r);

            [nums[l], nums[i]] = [nums[i], nums[l]];
        }
    }
}

Dry Run

Let's dry-run our algorithm for Example 1.

Input: nums = [1, 2, 3]

// in permute function
Step 1: vector<vector<int>> result

Step 2: _getPermutations(result, nums, 0, nums.size() - 1)
        _getPermutations(result, nums, 0, 2)

// in _getPermutations function
Step 3: if l == r
           0 == 2
           false

        else
          loop for i = l; i <= r
            i = 0
            0 <= 2
            true

            swap(nums[l], nums[i])
            swap(nums[0], nums[0])
            nums = [1, 2, 3]

            _getPermutations(result, nums, l + 1, r)
            _getPermutations(result, nums, 0 + 1, 2)
            _getPermutations(result, nums, 1, 2)

Step 4: if l == r
           1 == 2
           false

        else
          loop for i = l; i <= r
            i = 1
            1 <= 2
            true

            swap(nums[l], nums[i])
            swap(nums[1], nums[1])
            nums = [1, 2, 3]

            _getPermutations(result, nums, l + 1, r)
            _getPermutations(result, nums, 1 + 1, 2)
            _getPermutations(result, nums, 2, 2)

Step 5: if l == r
           2 == 2
           true
           result.push_back(nums)
           result = [[1, 2, 3]]
           return

           // We return to step 4

Step 6: swap(nums[l], nums[i])
        swap(nums[1], nums[1])
        nums = [1, 2, 3]

        i++
        i = 2
        loop for i <= r
            i = 2
            2 <= 2
            true

            swap(nums[l], nums[i])
            swap(nums[1], nums[2])
            nums = [1, 3, 2]

            _getPermutations(result, nums, l + 1, r)
            _getPermutations(result, nums, 1 + 1, 2)
            _getPermutations(result, nums, 2, 2)

Step 7: if l == r
           2 == 2
           true
           result.push_back(nums)
           result = [[1, 2, 3], [1, 3, 2]]
           return

           // We return to step 6

Step 8: swap(nums[l], nums[i])
        swap(nums[1], nums[2])
        nums = [1, 2, 3]

        i++
        i = 3
        loop for i <= r
            i = 3
            3 <= 2
            false

        // we backtrack to step 3

Step 9: swap(nums[l], nums[i])
        swap(nums[0], nums[0])
        nums = [1, 2, 3]

        i++
        i = 1
        loop for i <= r
            i = 1
            1 <= 2
            true

            swap(nums[l], nums[i])
            swap(nums[0], nums[1])
            nums = [2, 1, 3]

            _getPermutations(result, nums, l + 1, r)
            _getPermutations(result, nums, 0 + 1, 2)
            _getPermutations(result, nums, 1, 2)

Step 10: if l == r
            1 == 2
            false

         else
            for i = l; i <= r
            i = 1
            1 <= 2
            true

            swap(nums[l], nums[i])
            swap(nums[1], nums[1])
            nums = [2, 1, 3]

            _getPermutations(result, nums, l + 1, r)
            _getPermutations(result, nums, 1 + 1, 2)
            _getPermutations(result, nums, 2, 2)

Step 11: if l == r
            2 == 2
            true
            result.push_back(nums)
            result = [[1, 2, 3], [1, 3, 2], [2, 1, 3]]
            return

            // We return to step 10

We similarly backtrack to generate the rest of the solution
We return the solution as

[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
Share this post!