Open In App

Different Ways to Generate Permutations of an Array

Last Updated : 03 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Permutations are like the magic wand of combinatorics, allowing us to explore the countless ways elements can be rearranged within an array. Whether you’re a coder, a math enthusiast, or someone on a quest to solve a complex problem, understanding how to generate all permutations of an array is a valuable skill. In this article, we are going the know Different Ways to Generate Permutations of an Array

What does Permutations of an Array Means?

Imagine you have three letters, A, B, and C, and you want to make words out of them. You can arrange them in different orders, and those arrangements are called permutations. Here are the possibilities: ABC, ACB, BAC, BCA, CBA, CAB. This is all about permutations, where order matters.

Now, the tricky part is that people sometimes use the term “combinations” when they mean permutations. But mathematically, there’s a difference. Combinations are about picking things without caring about the order. For example, when rolling two dice and looking at the sum, it doesn’t matter if you roll a 3 and a 4 or a 4 and a 3, the result is the same. That’s a combination where order doesn’t matter.

How Many Permutations Can Be Generated?

The number of permutations that can be generated from a set of elements depends on the size of the set/array. In combinatorics, the formula for calculating the number of permutations of a set of “n” distinct elements taken “r” at a time is given by:

P(n, r) = \frac{n!}{(n - r)!}

Where:

  • P(n,r) represents the number of permutations.
  • n is the total number of distinct elements.
  • r is the number of elements taken at a time.
  • n! (read as “n factorial”) represents the product of all positive integers from 1 to n.

If you want to generate all permutations of a given set (where “r” is equal to “n”), the formula simplifies to:

P(n,n) = n!

So, for a set of “n” distinct elements, you can generate “n!” (n factorial) permutations. The number of permutations grows rapidly as “n” increases. For example, if you have 3 elements, there are 3! = 6 permutations, but if you have 4 elements, there are 4! = 24 permutations, and so on.

Examples:

Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
Explanation: It generates all permutations of the elements in the vector (3!=6) i.e [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

Input: nums = [0,1]
Output: [[0,1],[1,0]]
Explanation: It generates all permutations of the elements in the vector (2!=2) i.e [[0,1],[1,0]]

Input: nums = [1]
Output: [[1]]
Explanation: It generates all permutations of the elements in the vector (1!=1) i.e [[1]]

Different Ways to Generate Permutations of an Array:

  1. Simple Recursive Algorithm for Generating All Permutations of an Array
  2. Iterative Algorithm for Generating All Permutations of an Array
  3. Heap’s Algorithm for Generating All Permutations of an Array
  4. Steinhaus Johnson Trotter Algorithm for Generating All Permutations of an Array

1. Simple Recursive Algorithm for Generating All Permutations of an Array:

The simple recursive algorithm for generating all permutations of an array works like a branching tree. It starts with one element, explores all possible choices for the next element, and repeats this process for each subsequent element. This recursive “tree” expands until it covers all permutations, ensuring that no arrangement is missed. It’s like systematically trying out different orders for the elements, gradually building each permutation, one step at a time.

Algorithm:

  • To generate all the permutations of an array from index l to r, fix an element at index l and recur for the index l+1 to r.
  • Backtrack and fix another element at index l and recur for index l+1 to r.
  • Repeat the above steps to generate all the permutations.

Advantage:

  • This algorithm is easy to understand and implement, making it accessible to programmers of all levels.
  • It operates in-place, without the need for additional data structures, which can be memory-efficient.
  • It can be quite efficient for small arrays, and in some cases, its performance may be adequate.

2. Iterative Algorithm for Generating All Permutations of an Array:

The iterative algorithm for generating permutations efficiently arranges array elements in a systematic order, avoiding the complexities of backtracking. It consistently creates the next lexicographically greater permutation and ensures complete coverage without needing to backtrack, making it a straightforward and efficient approach to generating all possible permutations.

Algorithm:

  • Start with the original array.
  • Use indices to keep track of the elements to permute.
  • Repeat the following until there are no more permutations:
    • Swap elements to generate the next permutation.
    • Update the indices.
  • Continue until all permutations are generated.

Advantage:

  • Efficiency: It generates permutations in a predictable order without the need for backtracking, resulting in efficient and straightforward code.
  • No Stack Overhead: Unlike recursive methods, it doesn’t consume additional memory due to function call stacks, making it more memory-efficient.

3. Heap’s Algorithm:

Heaps algorithms are used to generate all the possible permutations of n-decimals of a number. This algorithm minimizes the movements, basically, it generates each permutation from the previous one by interchanging a single element while other elements are not disturbed.

Algorithm:

  • Calculate all the possible permutations of the first N-1 digits adjoining the last element to each of these permutations.
  • Iterate the digits, and check if N is an odd number then swap the first digit with the last digit and if N is an even number then swap the ith element with the last element.
  • After repeating the above steps, Algorithm produces all the permutations of N.

Advantages:

  • Heap’s Algorithm is implemented using iteration, making it non-recursive.
  • It generates permutations in-place, without requiring additional memory for data structures like stacks or recursion.

4. Steinhaus Johnson Trotter Algorithm:

The Steinhaus Johnson Trotter algorithm’s intuitive idea is to explore permutations by moving elements in a coordinated, directional manner. It ensures that every permutation is generated, and it can be particularly useful for problems where understanding the order of permutations is essential. The algorithm provides a different perspective on permutation generation compared to more traditional methods like Heap’s Algorithm or recursive approaches.

The core idea is as follows:

  • Directional Movement: The algorithm starts with an initial permutation, often in ascending order, and assigns a direction (left or right) to each element in the permutation.
  • Mobile Element: A “mobile” element is defined as an element that can move in its current direction. It’s larger than the element it’s facing in its direction. Initially, the rightmost element is mobile.
  • Swap and Flip: The algorithm performs a series of swaps between the mobile element and the adjacent element it’s facing. After each swap, the direction of both elements is reversed.
  • Iterative Process: This swapping and direction reversal process continues iteratively until there are no more mobile elements.
  • Resulting Permutations: As the algorithm progresses, it generates permutations while maintaining a sense of movement and direction, creating a unique visual representation of permutations.

Advantages:

  • Minimizes element swaps, reducing computational costs.
  • Preserves inversion properties of permutations.
  • Ideal for combinatorial and mathematical applications.
  • No backtracking required, simplifying implementation.
  • Memory-efficient.


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads