Shortest Path using Meet In The Middle

Last Updated : 11 Jul, 2025

Given a permutation P = p1, p2, ...., pn of first n natural numbers (1 ? n ? 10). One can swap any two consecutive elements pi and pi + 1 (1 ? i < n). The task is to find the minimum number of swaps to change P to another permutation P' = p'1, p'2, ...., p'n.

Examples: 

Input: P = "213", P' = "321"
Output: 2
213 <-> 231 <-> 321

Input: P = "1234", P' = "4123"
Output: 3

Approach: This problem can be solved using Dijkstra's Shortest Path Algorithm. Seem like there is nothing related to a graph in the statement. But assume one permutation is one vertex, then every swap of a permutation's elements is an edge which connects this vertex with another vertex. So finding the minimum number of swaps now becomes a simple BFS/shortest path problem.
Now let's analyze time complexity. We have n! vertices, each vertex has n - 1 adjacent vertices. We also have to store vertices visited state by map because their representations are hard to be stored by normal arrays. So total time complexity is O(N log(N!) * N!). Meet In The Middle technique can be used to make the solution faster.

Meet In The Middle solution is similar to Dijkstra's solution with some modifications.

  • Let P be the start vertex and P' be the finish Vertex.
  • Let both start and finish be roots. We start BFS from both the roots, start and finish at the same time but using only one queue.
  • Push start and finish into queue's back, visitedstart = visitedfinish = true.
  • Let srcu be the root of vertex u in BFS progression. So, srcstart = start and srcfinish = finish.
  • Let Du be the shortest distance from vertex u to it's tree's root. So Dstart = Dfinish = 0.
  • While queue is not empty, pop queue's front which is vertex u then push all vertices v which are adjacent with u and haven't been visited yet (visitedv = false) into queue's back, then let Dv = Du + 1, srcv = srcu and visitedv = true. Especially, if v was visited and srcv != srcu then we can immediately return Du + Dv + 1.

Below is the implementation of the above approach: 

C++
// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;

// Function to find minimum number of
// swaps to make another permutation
int ShortestPath(int n, string start, string finish)
{
    unordered_map<string, bool> visited;
    unordered_map<string, int> D;
    unordered_map<string, string> src;

    visited[start] = visited[finish] = true;
    D[start] = D[finish] = 0;
    src[start] = start;
    src[finish] = finish;

    queue<string> q;
    q.push(start);
    q.push(finish);

    while (!q.empty()) {

        // Take top vertex of the queue
        string u = q.front();
        q.pop();

        // Generate n - 1 of it's permutations
        for (int i = 1; i < n; i++) {

            // Generate next permutation
            string v = u;
            swap(v[i], v[i - 1]);

            // If v is not visited
            if (!visited[v]) {

                // Set it visited
                visited[v] = true;

                // Make root of u and root of v equal
                src[v] = src[u];

                // Increment it's distance by 1
                D[v] = D[u] + 1;

                // Push this vertex into queue
                q.push(v);
            }

            // If it is already visited
            // and roots are different
            // then answer is found
            else if (src[u] != src[v])
                return D[u] + D[v] + 1;
        }
    }
}

// Driver code
int main()
{
    string p1 = "1234", p2 = "4123";
    int n = p1.length();
    cout << ShortestPath(n, p1, p2);

    return 0;
}
Java
// Java implementation of the approach 
import java.util.*;
 
class GFG{
     
// Function to find minimum number of
// swaps to make another permutation
static int ShortestPath(int n, String start,
                               String finish)
{
    HashMap<String,
            Boolean> visited = new HashMap<String,
                                           Boolean>(); 
    HashMap<String,
            Integer> D = new HashMap<String,
                                     Integer>(); 
    HashMap<String,
            String> src = new HashMap<String,
                                      String>(); 
     
    visited.put(start, true);
    visited.put(finish, true);
     
    D.put(start, 0);
    D.put(finish, 0);
     
    src.put(start, start);
    src.put(finish, finish);
    Queue<String> q = new LinkedList<>(); 
    q.add(start);
    q.add(finish);
 
    while (q.size() != 0) 
    {
        
        // Take top vertex of the queue
        String u = (String)q.peek();
        q.remove();
 
        // Generate n - 1 of it's permutations
        for(int i = 1; i < n; i++)
        {
            
            // Generate next permutation
            StringBuilder tmp = new StringBuilder(u);
            char t = tmp.charAt(i);
            tmp.setCharAt(i, tmp.charAt(i - 1));
            tmp.setCharAt(i - 1, t);
             
            String v = tmp.toString();
             
            // If v is not visited
            if (!visited.getOrDefault(v, false))
            {
                
                // Set it visited
                visited.put(v, true);
 
                // Make root of u and root of v equal
                src.put(v, src.get(u));
 
                // Increment it's distance by 1
                D.put(v, D.get(u) + 1);
 
                // Push this vertex into queue
                q.add(v);
            }
 
            // If it is already visited
            // and roots are different
            // then answer is found
            else if (src.get(u) != src.get(v))
                return D.get(u) + D.get(v) + 1;
        }
    }
    return 0;
}
     
// Driver Code
public static void main(String[] args)
{
    String p1 = "1234", p2 = "4123";
    int n = p1.length();
     
    System.out.println(ShortestPath(n, p1, p2));
}
}

// This code is contributed by pratham76
Python3
# Python3 implementation of the approach
from collections import deque, defaultdict

# Function to find minimum number of
# swaps to make another permutation
def shortestPath(n: int, start: str, finish: str) -> int:
    visited, D, src = defaultdict(lambda: False), defaultdict(
        lambda: 0), defaultdict(lambda: '')
    visited[start] = visited[finish] = True
    D[start] = D[finish] = 0
    src[start], src[finish] = start, finish

    q = deque()
    q.append(start)
    q.append(finish)

    while q:

        # Take top vertex of the queue
        u = q[0]
        q.popleft()

        # Generate n - 1 of it's permutations
        for i in range(n):
            v = list(u)
            v[i], v[i - 1] = v[i - 1], v[i]

            v = ''.join(v)

            if not visited[v]:
                
                # Set it visited
                visited[v] = True

                # Make root of u and root of v equal
                src[v] = src[u]

                # Increment it's distance by 1
                D[v] = D[u] + 1

                # Push this vertex into queue
                q.append(v)

            # If it is already visited
            # and roots are different
            # then answer is found
            elif u in src and src[u] != src[v]:
                return D[u] + D[v] + 1

# Driver Code
if __name__ == "__main__":

    p1 = "1234"
    p2 = "4123"
    n = len(p1)
    print(shortestPath(n, p1, p2))

# This code is contributed by
# sanjeev2552
C#
// C# implementation of the approach 
using System;
using System.Collections; 
using System.Text; 
using System.Collections.Generic; 

class GFG{
    
// Function to find minimum number of
// swaps to make another permutation
static int ShortestPath(int n, string start,
                               string finish)
{
    Dictionary<string,
               bool> visited = new Dictionary<string,
                                              bool>(); 
    Dictionary<string,
               int> D = new Dictionary<string,
                                       int>(); 
    Dictionary<string,
               string> src = new Dictionary<string,
                                            string>(); 
    
    visited[start] = true;
    visited[finish] = true;
    
    D[start] = 0;
    D[finish] = 0;
    
    src[start] = start;
    src[finish] = finish;

    Queue q = new Queue();
    q.Enqueue(start);
    q.Enqueue(finish);

    while (q.Count != 0) 
    {
        
        // Take top vertex of the queue
        string u = (string)q.Peek();
        q.Dequeue();

        // Generate n - 1 of it's permutations
        for(int i = 1; i < n; i++)
        {
            
            // Generate next permutation
            StringBuilder tmp = new StringBuilder(u);
            char t = tmp[i];
            tmp[i] = tmp[i - 1];
            tmp[i - 1] = t;
            
            string v = tmp.ToString();
            
            // If v is not visited
            if (!visited.GetValueOrDefault(v, false))
            {
                
                // Set it visited
                visited[v] = true;

                // Make root of u and root of v equal
                src[v] = src[u];

                // Increment it's distance by 1
                D[v] = D[u] + 1;

                // Push this vertex into queue
                q.Enqueue(v);
            }

            // If it is already visited
            // and roots are different
            // then answer is found
            else if (src[u] != src[v])
                return D[u] + D[v] + 1;
        }
    }
    return 0;
}
    
// Driver Code
public static void Main(string[] args)
{
    string p1 = "1234", p2 = "4123";
    int n = p1.Length;
    
    Console.Write(ShortestPath(n, p1, p2));
}
}

// This code is contributed by rutvik_56
JavaScript
<script>

  // Function to find minimum number of
  // swaps to make another permutation
  function ShortestPath(n, start, finish) {
      let visited = new Map();
      let D = new Map();
      let src = new Map();

      visited.set(start, true);
      visited.set(finish, true);
      D.set(start, 0);
      D.set(finish, 0);
      src.set(start, start);
      src.set(finish, finish);

      let q = [];
      q.push(start);
      q.push(finish);

      while (q.length > 0) {

          // Take top vertex of the queue
          let u = q.shift();

          // Generate n - 1 of it's permutations
          for (let i = 1; i < n; i++) {

              // Generate next permutation
              let v = u;
              let temp = v[i];
              v = v.substring(0, i) + v[i - 1] + v.substring(i + 1);
              v = v.substring(0, i - 1) + temp + v.substring(i);

              // If v is not visited
              if (!visited.has(v)) {

                  // Set it visited
                  visited.set(v, true);

                  // Make root of u and root of v equal
                  src.set(v, src.get(u));

                  // Increment it's distance by 1
                  D.set(v, D.get(u) + 1);

                  // Push this vertex into queue
                  q.push(v);
              }

              // If it is already visited
              // and roots are different
              // then answer is found
              else if (src.get(u) !== src.get(v))
                  return D.get(u) + D.get(v) + 1;
          }
      }
  }

  // Driver code
  function main() {
      let p1 = "1234", p2 = "4123";
      let n = p1.length;
      console.log(ShortestPath(n, p1, p2));
  }

  main();



</script>

Output
3
Comment