Open In App

Arrange array elements such that last digit of an element is equal to first digit of the next element

Given an array arr[] of integers, the task is to arrange the array elements such that the last digit of an element is equal to first digit of the next element.

Examples: 

Input: arr[] = {123, 321} 
Output: 123 321

Input: arr[] = {451, 378, 123, 1254} 
Output: 1254 451 123 378 
 

Naive approach: Find all the permutations of the array elements and then print the arranged array which meets the required condition. The time complexity of this approach is O(N!)

Efficient approach: Create a directed graph where there will be a directed edge from a node A to node B if the last digit of the number represented by Node A is equal to the first digit of the number represented by Node B. Now, find the Eulerian path for the graph formed. The complexity of the above algorithm is O(E * E) where E is the number of edges in the graph.

Below is the implementation of the above approach:




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// To store the array elements
vector<string> arr;
 
// Adjacency list for the graph nodes
vector<vector<int> > graph;
 
// To store the euler path
vector<string> path;
 
// Print eulerian path
bool print_euler(int i, int visited[], int count)
{
    // Mark node as visited
    // and increase the count
    visited[i] = 1;
    count++;
 
    // If all the nodes are visited
    // then we have traversed the euler path
    if (count == graph.size()) {
        path.push_back(arr[i]);
        return true;
    }
 
    // Check if the node lies in euler path
    bool b = false;
 
    // Traverse through remaining edges
    for (int j = 0; j < graph[i].size(); j++)
        if (visited[graph[i][j]] == 0) {
            b |= print_euler(graph[i][j], visited, count);
        }
 
    // If the euler path is found
    if (b) {
        path.push_back(arr[i]);
        return true;
    }
 
    // Else unmark the node
    else {
        visited[i] = 0;
        count--;
        return false;
    }
}
 
// Function to create the graph and
// print the required path
void connect()
{
    int n = arr.size();
    graph.clear();
    graph.resize(n);
 
    // Connect the nodes
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j)
                continue;
 
            // If the last character matches with the
            // first character
            if (arr[i][arr[i].length() - 1] == arr[j][0]) {
                graph[i].push_back(j);
            }
        }
    }
 
    // Print the path
    for (int i = 0; i < n; i++) {
        int visited[n] = { 0 }, count = 0;
 
        // If the euler path starts
        // from the ith node
        if (print_euler(i, visited, count))
            break;
    }
 
    // Print the euler path
    for (int i = path.size() - 1; i >= 0; i--) {
        cout << path[i];
        if (i != 0)
            cout << " ";
    }
}
// Driver code
int main()
{
    arr.push_back("451");
    arr.push_back("378");
    arr.push_back("123");
    arr.push_back("1254");
 
    // Create graph and print the path
    connect();
 
    return 0;
}




// Java implementation of the approach
import java.util.*;
 
class GFG{
 
// To store the array elements
static List<String> arr = new ArrayList<String>();
 
// Adjacency list for the graph nodes
static List<List<Integer>> graph = new ArrayList<List<Integer>>();
 
// To store the euler path
static List<String> path = new ArrayList<String>();
 
// Print eulerian path
static boolean print_euler(int i, int []visited,
                           int count)
{
     
    // Mark node as visited
    // and increase the count
    visited[i] = 1;
    count++;
 
    // If all the nodes are visited
    // then we have traversed the euler path
    if (count == graph.size())
    {
        path.add(arr.get(i));
        return true;
    }
 
    // Check if the node lies in euler path
    boolean b = false;
 
    // Traverse through remaining edges
    for(int j = 0; j < graph.get(i).size(); j++)
        if (visited[graph.get(i).get(j)] == 0)
        {
            b |= print_euler(graph.get(i).get(j),
                             visited, count);
        }
 
    // If the euler path is found
    if (b)
    {
        path.add(arr.get(i));
        return true;
    }
 
    // Else unmark the node
    else
    {
        visited[i] = 0;
        count--;
        return false;
    }
}
 
// Function to create the graph and
// print the required path
static void connect()
{
    int n = arr.size();
    graph = new ArrayList<List<Integer>>(n);
 
    for(int i = 0; i < n; i++)
    {
        graph.add(new ArrayList<Integer>());
    }
     
    // Connect the nodes
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            if (i == j)
                continue;
 
            // If the last character matches with the
            // first character
            if (arr.get(i).charAt((arr.get(i).length()) - 1) ==
                arr.get(j).charAt(0))
            {
                graph.get(i).add(j);
            }
        }
    }
 
    // Print the path
    for(int i = 0; i < n; i++)
    {
        int []visited = new int[n];
        int count = 0;
 
        // If the euler path starts
        // from the ith node
        if (print_euler(i, visited, count))
            break;
    }
 
    // Print the euler path
    for(int i = path.size() - 1; i >= 0; i--)
    {
        System.out.print(path.get(i));
         
        if (i != 0)
            System.out.print(" ");
    }
}
 
// Driver code
public static void main(String []args)
{
    arr.add("451");
    arr.add("378");
    arr.add("123");
    arr.add("1254");
 
    // Create graph and print the path
    connect();
}
}
 
// This code is contributed by pratham76




# Python3 implementation of the approach
 
# Print eulerian path
 
 
def print_euler(i, visited, count):
 
    # Mark node as visited
    # and increase the count
    visited[i] = 1
    count += 1
 
    # If all the nodes are visited then
    # we have traversed the euler path
    if count == len(graph):
        path.append(arr[i])
        return True
 
    # Check if the node lies in euler path
    b = False
 
    # Traverse through remaining edges
    for j in range(0, len(graph[i])):
        if visited[graph[i][j]] == 0:
            b |= print_euler(graph[i][j], visited, count)
 
    # If the euler path is found
    if b:
        path.append(arr[i])
        return True
 
    # Else unmark the node
    else:
        visited[i] = 0
        count -= 1
        return False
 
# Function to create the graph
# and print the required path
 
 
def connect():
 
    n = len(arr)
    # Connect the nodes
    for i in range(0, n):
        for j in range(0, n):
            if i == j:
                continue
 
            # If the last character matches
            # with the first character
            if arr[i][-1] == arr[j][0]:
                graph[i].append(j)
 
    # Print the path
    for i in range(0, n):
        visited = [0] * n
        count = 0
 
        # If the euler path starts
        # from the ith node
        if print_euler(i, visited, count):
            break
 
    # Print the euler path
    for i in range(len(path) - 1, -1, -1):
        print(path[i], end="")
        if i != 0:
            print(" ", end="")
 
 
# Driver code
if __name__ == "__main__":
 
    # To store the array elements
    arr = []
    arr.append("451")
    arr.append("378")
    arr.append("123")
    arr.append("1254")
 
    # Adjacency list for the graph nodes
    graph = [[] for i in range(len(arr))]
 
    # To store the euler path
    path = []
 
    # Create graph and print the path
    connect()
 
# This code is contributed by Rituraj Jain




// C# implementation of the approach
using System;
using System.Collections;
using System.Collections.Generic;
 
class GFG
{
 
// To store the array elements
static List<string> arr = new List<string>();
 
// Adjacency list for the graph nodes
static List<List<int> > graph=  new List<List<int>>();
 
// To store the euler path
static List<string> path = new List<string>();
 
// Print eulerian path
static bool print_euler(int i, int []visited, int count)
{
    // Mark node as visited
    // and increase the count
    visited[i] = 1;
    count++;
 
    // If all the nodes are visited
    // then we have traversed the euler path
    if (count == graph.Count) {
        path.Add(arr[i]);
        return true;
    }
 
    // Check if the node lies in euler path
    bool b = false;
 
    // Traverse through remaining edges
    for (int j = 0; j < graph[i].Count; j++)
        if (visited[graph[i][j]] == 0) {
            b |= print_euler(graph[i][j], visited, count);
        }
 
    // If the euler path is found
    if (b) {
        path.Add(arr[i]);
        return true;
    }
 
    // Else unmark the node
    else {
        visited[i] = 0;
        count--;
        return false;
    }
}
 
// Function to create the graph and
// print the required path
static void connect()
{
    int n = arr.Count;
    graph=new List<List<int>>(n);
 
    for(int i = 0; i < n; i++)
    {
        graph.Add(new List<int>());
    }
     
    // Connect the nodes
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j)
                continue;
 
            // If the last character matches with the
            // first character
            if (arr[i][(arr[i].Length) - 1] == arr[j][0]) {
                graph[i].Add(j);
            }
        }
    }
 
    // Print the path
    for (int i = 0; i < n; i++) {
 
        int []visited = new int[n];
        int count = 0;
 
        // If the euler path starts
        // from the ith node
        if (print_euler(i, visited, count))
            break;
    }
 
    // Print the euler path
    for (int i = path.Count - 1; i >= 0; i--) {
        Console.Write(path[i]);
        if (i != 0)
            Console.Write(" ");
    }
}
 
// Driver code
public static void Main(params string []args)
{
    arr.Add("451");
    arr.Add("378");
    arr.Add("123");
    arr.Add("1254");
 
    // Create graph and print the path
    connect();
}
}
 
// This code is contributed by rutvik_56.




// JavaScript implementation of the approach
// To store the array elements
let arr = [];
 
// Adjacency list for the graph nodes
let graph = [];
 
// To store the euler path
let path = [];
 
// Print eulerian path
function print_euler(i, visited, count) {
    // Mark node as visited
    // and increase the count
    visited[i] = 1;
    count++;
 
    // If all the nodes are visited
    // then we have traversed the euler path
    if (count == graph.length) {
        path.push(arr[i]);
        return true;
    }
 
    // Check if the node lies in euler path
    let b = false;
 
    // Traverse through remaining edges
    for (let j = 0; j < graph[i].length; j++)
        if (visited[graph[i][j]] == 0) {
            b |= print_euler(graph[i][j], visited, count);
        }
 
    // If the euler path is found
    if (b) {
        path.push(arr[i]);
        return true;
    }
 
    // Else unmark the node
    else {
        visited[i] = 0;
        count--;
        return false;
    }
}
 
// Function to create the graph and
// print the required path
function connect() {
    let n = arr.length;
    graph.length = 0;
    graph.length = n;
 
    // Connect the nodes
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            if (i == j) continue;
 
            // If the last character matches with the
            // first character
            if (arr[i][arr[i].length - 1] == arr[j][0]) {
                graph[i].push(j);
            }
        }
    }
 
    // Print the path
    for (let i = 0; i < n; i++) {
        let visited = new Array(n).fill(0);
        let count = 0;
 
        // If the euler path starts
        // from the ith node
        if (print_euler(i, visited, count)) break;
    }
 
    // Print the euler path
    for (let i = path.length - 1; i >= 0; i--) {
        console.log(path[i]);
        if (i != 0) console.log(" ");
    }
}
 
// Driver code
(function () {
    arr.push("451");
    arr.push("378");
    arr.push("123");
    arr.push("1254");
 
    // Create graph and print the path
    connect();
})();

Output
1254 451 123 378






Time Complexity : O(N* log(N))

Auxiliary Space: O(N)

Approach:(graph-based)

The approach is to create a graph where each number is a node and add an edge between two nodes if the last digit of one number matches the first digit of the other number. Then, we use an algorithm to find the Eulerian path in the graph, which represents the valid arrangement of numbers. Finally, we print the Eulerian path in reverse order to obtain the required arrangement of numbers.




#include <bits/stdc++.h>
using namespace std;
 
// To store the array elements
vector<string> arr;
 
// Adjacency list for the graph nodes
vector<vector<int>> graph;
 
// To store the euler path
vector<string> path;
 
// Print eulerian path
bool print_euler(int i, int visited[], int count) {
    // Mark node as visited
    // and increase the count
    visited[i] = 1;
    count++;
 
    // If all the nodes are visited
    // then we have traversed the euler path
    if (count == graph.size()) {
        path.push_back(arr[i]);
        return true;
    }
 
    // Check if the node lies in euler path
    bool b = false;
 
    // Traverse through remaining edges
    for (int j = 0; j < graph[i].size(); j++) {
        if (visited[graph[i][j]] == 0) {
            b |= print_euler(graph[i][j], visited, count);
        }
    }
 
    // If the euler path is found
    if (b) {
        path.push_back(arr[i]);
        return true;
    }
 
    // Else unmark the node
    else {
        visited[i] = 0;
        count--;
        return false;
    }
}
 
// Function to create the graph and
// print the required path
void connect() {
    int n = arr.size();
    graph.clear();
    graph.resize(n);
 
    // Connect the nodes
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) continue;
 
            // If the last character matches with the
            // first character
            if (arr[i][arr[i].length() - 1] == arr[j][0]) {
                graph[i].push_back(j);
            }
        }
    }
 
    // Print the path
    for (int i = 0; i < n; i++) {
        int visited[n] = {0}, count = 0;
 
        // If the euler path starts
        // from the ith node
        if (print_euler(i, visited, count)) break;
    }
 
    // Print the euler path
    for (int i = path.size() - 1; i >= 0; i--) {
        cout << path[i];
        if (i != 0) cout << " ";
    }
}
 
// Driver code
int main() {
    arr.push_back("451");
    arr.push_back("378");
    arr.push_back("123");
    arr.push_back("1254");
 
    // Create graph and print the path
    connect();
 
    return 0;
}




import java.util.ArrayList;
 
public class EulerPath {
 
    // To store the array elements
    static ArrayList<String> arr = new ArrayList<>();
 
    // Adjacency list for the graph nodes
    static ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
 
    // To store the Euler path
    static ArrayList<String> path = new ArrayList<>();
 
    // Print Eulerian path
    static boolean printEuler(int i, int[] visited, int count) {
        // Mark node as visited and increase the count
        visited[i] = 1;
        count++;
 
        // If all the nodes are visited then we have traversed the Euler path
        if (count == graph.size()) {
            path.add(arr.get(i));
            return true;
        }
 
        // Check if the node lies in the Euler path
        boolean b = false;
 
        // Traverse through remaining edges
        for (int j = 0; j < graph.get(i).size(); j++) {
            if (visited[graph.get(i).get(j)] == 0) {
                b |= printEuler(graph.get(i).get(j), visited, count);
            }
        }
 
        // If the Euler path is found
        if (b) {
            path.add(arr.get(i));
            return true;
        }
 
        // Else unmark the node
        else {
            visited[i] = 0;
            count--;
            return false;
        }
    }
 
    // Function to create the graph and print the required path
    static void connect() {
        int n = arr.size();
        graph.clear();
 
        // Initialize adjacency list
        for (int i = 0; i < n; i++) {
            graph.add(new ArrayList<>());
        }
 
        // Connect the nodes
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (i == j) continue;
 
                // If the last character matches with the first character
                if (arr.get(i).charAt(arr.get(i).length() - 1) == arr.get(j).charAt(0)) {
                    graph.get(i).add(j);
                }
            }
        }
 
        // Print the path
        for (int i = 0; i < n; i++) {
            int[] visited = new int[n];
            int count = 0;
 
            // If the Euler path starts from the ith node
            if (printEuler(i, visited, count)) {
                break;
            }
        }
 
        // Print the Euler path
        for (int i = path.size() - 1; i >= 0; i--) {
            System.out.print(path.get(i));
            if (i != 0) System.out.print(" ");
        }
    }
 
    // Driver code
    public static void main(String[] args) {
        arr.add("451");
        arr.add("378");
        arr.add("123");
        arr.add("1254");
 
        // Create graph and print the path
        connect();
    }
}




# To store the array elements
arr = []
 
# Adjacency list for the graph nodes
graph = []
 
# To store the euler path
path = []
 
# Print eulerian path
def print_euler(i, visited, count):
    global graph, arr, path
    # Mark node as visited and increase the count
    visited[i] = 1
    count += 1
 
    # If all the nodes are visited then we have traversed the euler path
    if count == len(graph):
        path.append(arr[i])
        return True
 
    # Check if the node lies in euler path
    b = False
 
    # Traverse through remaining edges
    for j in graph[i]:
        if visited[j] == 0:
            b |= print_euler(j, visited, count)
 
    # If the euler path is found
    if b:
        path.append(arr[i])
        return True
 
    # Else unmark the node
    else:
        visited[i] = 0
        count -= 1
        return False
 
# Function to create the graph and print the required path
def connect():
    global graph, arr, path
    n = len(arr)
    graph = [[] for _ in range(n)]
 
    # Connect the nodes
    for i in range(n):
        for j in range(n):
            if i == j:
                continue
 
            # If the last character matches with the first character
            if arr[i][-1] == arr[j][0]:
                graph[i].append(j)
 
    # Print the path
    for i in range(n):
        visited = [0] * n
        count = 0
 
        # If the euler path starts from the ith node
        if print_euler(i, visited, count):
            break
 
    # Print the euler path
    print(" ".join(path[::-1]))
 
# Driver code
if __name__ == "__main__":
    arr = ["451", "378", "123", "1254"]
    # Create graph and print the path
    connect()




using System;
using System.Collections.Generic;
 
namespace EulerianPath
{
    class GFG
    {
        // To store the array elements
        static List<string> arr = new List<string>();
 
        // Adjacency list for the graph nodes
        static List<List<int>> graph = new List<List<int>>();
 
        // To store the euler path
        static List<string> path = new List<string>();
 
        // Print eulerian path
        static bool PrintEuler(int i, int[] visited, int count)
        {
            // Mark node as visited and increase the count
            visited[i] = 1;
            count++;
 
            // If all the nodes are visited, then we have traversed the euler path
            if (count == graph.Count)
            {
                path.Add(arr[i]);
                return true;
            }
 
            // Check if the node lies in euler path
            bool b = false;
 
            // Traverse through remaining edges
            foreach (int j in graph[i])
            {
                if (visited[j] == 0)
                {
                    b |= PrintEuler(j, visited, count);
                }
            }
 
            // If the euler path is found
            if (b)
            {
                path.Add(arr[i]);
                return true;
            }
            // Else unmark the node
            else
            {
                visited[i] = 0;
                count--;
                return false;
            }
        }
 
        // Function to create the graph and print the required path
        static void Connect()
        {
            int n = arr.Count;
            graph.Clear();
            for (int i = 0; i < n; i++)
            {
                graph.Add(new List<int>());
            }
 
            // Connect the nodes
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (i == j) continue;
 
                    // If the last character matches with the first character
                    if (arr[i][arr[i].Length - 1] == arr[j][0])
                    {
                        graph[i].Add(j);
                    }
                }
            }
 
            // Print the path
            for (int i = 0; i < n; i++)
            {
                int[] visited = new int[n];
                int count = 0;
 
                // If the euler path starts from the ith node
                if (PrintEuler(i, visited, count)) break;
            }
 
            // Print the euler path
            for (int i = path.Count - 1; i >= 0; i--)
            {
                Console.Write(path[i]);
                if (i != 0) Console.Write(" ");
            }
        }
 
        // Driver code
        static void Main(string[] args)
        {
            arr.Add("451");
            arr.Add("378");
            arr.Add("123");
            arr.Add("1254");
 
            // Create graph and print the path
            Connect();
        }
    }
}




// To store the array elements
const arr = ["451", "378", "123", "1254"];
 
// Adjacency list for the graph nodes
const graph = [];
 
// To store the euler path
const path = [];
 
// Print eulerian path
function printEuler(i, visited, count) {
    // Mark node as visited and increase the count
    visited[i] = 1;
    count++;
 
    // If all the nodes are visited, then we have traversed the Euler path
    if (count === graph.length) {
        path.push(arr[i]);
        return true;
    }
 
    // Check if the node lies in the Euler path
    let found = false;
 
    // Traverse through remaining edges
    for (let j = 0; j < graph[i].length; j++) {
        if (visited[graph[i][j]] === 0) {
            found |= printEuler(graph[i][j], visited, count);
        }
    }
 
    // If the Euler path is found
    if (found) {
        path.push(arr[i]);
        return true;
    }
 
    // Else unmark the node
    else {
        visited[i] = 0;
        count--;
        return false;
    }
}
 
// Function to create the graph and print the required path
function connect() {
    const n = arr.length;
    graph.length = 0;
    for (let i = 0; i < n; i++) {
        graph.push([]);
        for (let j = 0; j < n; j++) {
            if (i === j) continue;
 
            // If the last character matches with the first character
            if (arr[i][arr[i].length - 1] === arr[j][0]) {
                graph[i].push(j);
            }
        }
    }
 
    // Print the path
    for (let i = 0; i < n; i++) {
        const visited = Array(n).fill(0);
        let count = 0;
 
        // If the Euler path starts from the ith node
        if (printEuler(i, visited, count)) break;
    }
 
    // Print the Euler path
    for (let i = path.length - 1; i >= 0; i--) {
        process.stdout.write(path[i]);
        if (i !== 0) process.stdout.write(" ");
    }
}
 
// Driver code
connect();

Output
1254 451 123 378






Time Complexity : O(n^2 * 2^n), where n is the number of strings in the input array. This is because for each pair of strings, we are comparing the last character of one string with the first character of the other string, and this takes O(n^2) time. In addition, we are using a recursive function to find the eulerian path, and the worst-case scenario involves traversing all the edges in the graph, which takes O(2^n) time.

Auxiliary Space:O(n + m), where n is the number of strings in the input array and m is the total number of edges in the graph. This is because we are using several auxiliary data structures such as vectors to store the array elements, adjacency list for the graph nodes, and the eulerian path. In addition, we are using an array to keep track of the visited nodes during the depth-first search, which takes O(n) space.


Article Tags :