Flattening a Linked List

Last Updated : 20 Oct, 2026

In a linked list, every node has two pointers: next and bottom. The heads of n linked lists are connected using the next pointer, while the bottom pointer points to the next node in the current linked list.

Each linked list is sorted in non-decreasing order of data, and the head nodes are also sorted in non-decreasing order.

Given the head of the first linked list, flatten the linked lists into a single sorted linked list such that every node is connected using only the bottom pointers.

Examples: 

Input:

409843057

Output: 5 -> 7 -> 8 -> 10 -> 19 -> 20 -> 22 -> 28 -> 40 -> 45.
Explanation:
Bottom pointer of 5 is pointing to 7.
Bottom pointer of 7 is pointing to 8.
Bottom pointer of 10 is pointing to 20 and so on.
So, after flattening the linked list the sorted list will be 5 -> 7 -> 8 -> 10 -> 19 -> 20 -> 22 -> 28 -> 40 -> 45.

Input:

409843058

Output: 5 -> 7 -> 8 -> 10 -> 19 -> 22 -> 28 -> 30 -> 50
Explanation:
Bottom pointer of 5 is pointing to 7.
Bottom pointer of 7 is pointing to 8.
Bottom pointer of 8 is pointing to 30 and so on.
So, after flattening the linked list the sorted list will be 5 -> 7 -> 8 -> 10 -> 19 -> 22 -> 28 -> 30 -> 50.

Try It Yourself
redirect icon

[Naive Approach] Recursion and Merging - O(n * n * m) Time and O(n) Space

The idea is similar to Merge two sorted linked lists. We recursively flatten the list connected through the next pointer and merge each sublist with the already flattened list in sorted order using the bottom pointer.

Working of Approach:

  • Using recursion, first go to the last head node.
  • Merge each linked list (connected via bottom pointers) with the already flattened list in sorted order.
  • Move one step back and merge the previous list with the merged result.
  • Continue this process until the first list is merged.
  • Return the final flattened and sorted list connected through bottom pointers.
C++
#include <bits/stdc++.h>
using namespace std;

class Node
{
  public:
    int data;
    Node *next, *bottom;

    Node(int newdata)
    {
        data = newdata;
        next = bottom = nullptr;
    }
};

// Utility function to merge two sorted linked lists
// using their bottom pointers
Node *merge(Node *head1, Node *head2)
{

    // A dummy first node to store the result list
    Node dummy(-1);

    // Tail points to the last result node to add new nodes
    // to the result
    Node *tail = &dummy;

    // Iterate till either head1 or head2 does not reach NULL
    while (head1 && head2)
    {

        if (head1->data <= head2->data)
        {

            // append head1 to the result
            tail->bottom = head1;
            head1 = head1->bottom;
        }
        else
        {

            // append head2 to the result
            tail->bottom = head2;
            head2 = head2->bottom;
        }

        // Move tail pointer to the next node
        tail = tail->bottom;
    }

    // Append the remaining nodes of non-null linked list
    if (!head1)
        tail->bottom = head2;
    else
        tail->bottom = head1;
    return (dummy.bottom);
}

// function to flatten the linked list
Node *flatten(Node *root)
{

    // Base Cases
    if (root == nullptr || root->next == nullptr)
        return root;

    // Recur for next list
    root->next = flatten(root->next);

    // Now merge the current and next list
    root = merge(root, root->next);

    // Return the root
    return root;
}

void printList(Node *head)
{
    Node *temp = head;
    while (temp != nullptr)
    {
        cout << temp->data;
        if (temp->bottom)
            cout << " -> ";
        temp = temp->bottom;
    }
    cout << endl;
}

int main()
{

    /* Create a hard-coded linked list:
        5 -> 10 -> 19 -> 28
        |    |     |
        V    V     V
        7    20    22
        |          |
        V          V
        8          50
        |
        V
        30
    */

    Node *head = new Node(5);
    head->bottom = new Node(7);
    head->bottom->bottom = new Node(8);
    head->bottom->bottom->bottom = new Node(30);

    head->next = new Node(10);
    head->next->bottom = new Node(20);

    head->next->next = new Node(19);
    head->next->next->bottom = new Node(22);
    head->next->next->bottom->bottom = new Node(50);

    head->next->next->next = new Node(28);

    head = flatten(head);

    printList(head);
    return 0;
}
C
#include <stdio.h>

struct Node
{
    int data;
    struct Node *next, *bottom;
};

// Utility function to merge two sorted linked lists using
// their bottom pointers
struct Node *merge(struct Node *head1, struct Node *head2)
{

    // A dummy first node to store the result list
    struct Node dummy;
    dummy.data = -1;
    dummy.bottom = NULL;

    // Tail points to the last result node to add new nodes
    // to the result
    struct Node *tail = &dummy;

    // Iterate till either head1 or head2 does not reach
    // NULL
    while (head1 && head2)
    {

        if (head1->data <= head2->data)
        {

            // append head1 to the result
            tail->bottom = head1;
            head1 = head1->bottom;
        }
        else
        {

            // append head2 to the result
            tail->bottom = head2;
            head2 = head2->bottom;
        }

        // Move tail pointer to the next node
        tail = tail->bottom;
    }

    // Append the remaining nodes of non-null linked list
    if (!head1)
        tail->bottom = head2;
    else
        tail->bottom = head1;

    return dummy.bottom;
}

// Function to flatten the linked list
struct Node *flatten(struct Node *root)
{

    // Base Cases
    if (root == NULL || root->next == NULL)
        return root;

    // Recur for next list
    root->next = flatten(root->next);

    // Now merge the current and next list
    root = merge(root, root->next);

    // Return the root
    return root;
}

void printList(struct Node *head)
{
    struct Node *temp = head;
    while (temp != NULL)
    {
        printf("%d", temp->data);
        if (temp->bottom)
            printf(" -> ");
        temp = temp->bottom;
    }
    printf("\n");
}

// Function to create a new node
struct Node *createNode(int newdata)
{
    struct Node *newnode = (struct Node *)malloc(sizeof(struct Node));
    newnode->data = newdata;
    newnode->next = NULL;
    newnode->bottom = NULL;
    return newnode;
}

int main()
{

    /* Create a hard-coded linked list:
        5 -> 10 -> 19 -> 28
        |    |     |
        V    V     V
        7    20    22
        |          |
        V          V
        8          50
        |
        V
        30
    */

    struct Node *head = createNode(5);
    head->bottom = createNode(7);
    head->bottom->bottom = createNode(8);
    head->bottom->bottom->bottom = createNode(30);

    head->next = createNode(10);
    head->next->bottom = createNode(20);

    head->next->next = createNode(19);
    head->next->next->bottom = createNode(22);
    head->next->next->bottom->bottom = createNode(50);

    head->next->next->next = createNode(28);

    head = flatten(head);

    printList(head);

    return 0;
}
Java
class Node {
    int data;
    Node next, bottom;

    Node(int newData)
    {
        data = newData;
        next = bottom = null;
    }
}

class GFG {

    // Utility function to merge two sorted linked lists
    // using their bottom pointers
    static Node merge(Node head1, Node head2)
    {

        // A dummy first node to store the result list
        Node dummy = new Node(-1);

        // Tail points to the last result node to add new
        // nodes to the result
        Node tail = dummy;

        // Iterate till either head1 or head2 does not reach
        // null
        while (head1 != null && head2 != null) {
            if (head1.data <= head2.data) {

                // Append head1 to the result
                tail.bottom = head1;
                head1 = head1.bottom;
            }
            else {

                // Append head2 to the result
                tail.bottom = head2;
                head2 = head2.bottom;
            }

            // Move tail pointer to the next node
            tail = tail.bottom;
        }

        // Append the remaining nodes of the non-null list
        if (head1 != null)
            tail.bottom = head1;
        else
            tail.bottom = head2;

        return dummy.bottom;
    }

    // Function to flatten the linked list
    static Node flatten(Node root)
    {

        // Base Cases
        if (root == null || root.next == null)
            return root;

        // Recur for next list
        root.next = flatten(root.next);

        // Now merge the current and next list
        root = merge(root, root.next);

        // Return the root
        return root;
    }

    static void printList(Node head)
    {
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.data);
            if (temp.bottom != null) {
                System.out.print(" -> ");
            }
            temp = temp.bottom;
        }
        System.out.println();
    }

    public static void main(String[] args)
    {

        /* Create a hard-coded linked list:
            5 -> 10 -> 19 -> 28
            |    |     |
            V    V     V
            7    20    22
            |          |
            V          V
            8          50
            |
            V
            30
        */

        Node head = new Node(5);
        head.bottom = new Node(7);
        head.bottom.bottom = new Node(8);
        head.bottom.bottom.bottom = new Node(30);

        head.next = new Node(10);
        head.next.bottom = new Node(20);

        head.next.next = new Node(19);
        head.next.next.bottom = new Node(22);
        head.next.next.bottom.bottom = new Node(50);

        head.next.next.next = new Node(28);

        head = flatten(head);

        printList(head);
    }
}
Python
class Node:
    def __init__(self, new_data):
        self.data = new_data
        self.next = None
        self.bottom = None

# Utility function to merge two sorted linked lists 
# using their bottom pointers
def merge(head1, head2):
  
    # A dummy first node to store the result list
    dummy = Node(-1)
    tail = dummy

    # Iterate till either head1 or head2 does not reach None
    while head1 and head2:
        if head1.data <= head2.data:
          
            # Append head1 to the result
            tail.bottom = head1
            head1 = head1.bottom
        else:
          
            # Append head2 to the result
            tail.bottom = head2
            head2 = head2.bottom
        
        # Move tail pointer to the next node
        tail = tail.bottom

    # Append the remaining nodes of the non-null linked list
    if head1:
        tail.bottom = head1
    else:
        tail.bottom = head2
    
    return dummy.bottom

# Function to flatten the linked list
def flatten(root):
  
    # Base Cases
    if root is None or root.next is None:
        return root

    # Recur for next list
    root.next = flatten(root.next)

    # Now merge the current and next list
    root = merge(root, root.next)

    # Return the root
    return root

def printList(node):
    while node is not None:
        print(f"{node.data}", end="")
        if node.bottom is not None:
            print(" -> ", end="")
        node = node.bottom
    print()

if __name__ == "__main__":
  
    # Create a hard-coded linked list:
    #     5 -> 10 -> 19 -> 28
    #     |    |     |   
    #     V    V     V    
    #     7    20    22    
    #     |          |    
    #     V          V    
    #     8          50    
    #     |               
    #     V               
    #     30 
    
    head = Node(5)
    head.bottom = Node(7)
    head.bottom.bottom = Node(8)
    head.bottom.bottom.bottom = Node(30)

    head.next = Node(10)
    head.next.bottom = Node(20)

    head.next.next = Node(19)
    head.next.next.bottom = Node(22)
    head.next.next.bottom.bottom = Node(50)

    head.next.next.next = Node(28)

    head = flatten(head)

    printList(head)
C#
using System;

class Node {
    public int data;
    public Node next;
    public Node bottom;

    public Node(int newData)
    {
        data = newData;
        next = null;
        bottom = null;
    }
}

class GFG {
    // Utility function to merge two sorted linked lists
    // using their bottom pointers
    static Node Merge(Node head1, Node head2)
    {
        // A dummy first node to store the result list
        Node dummy = new Node(-1);

        // Tail points to the last result node
        Node tail = dummy;

        // Iterate until either list becomes null
        while (head1 != null && head2 != null) {
            if (head1.data <= head2.data) {
                tail.bottom = head1;
                head1 = head1.bottom;
            }
            else {
                tail.bottom = head2;
                head2 = head2.bottom;
            }

            tail = tail.bottom;
        }

        // Append the remaining nodes
        if (head1 == null)
            tail.bottom = head2;
        else
            tail.bottom = head1;

        return dummy.bottom;
    }

    // Function to flatten the linked list
    static Node flatten(Node root)
    {
        // Base cases
        if (root == null || root.next == null)
            return root;

        // Recursively flatten the next list
        root.next = flatten(root.next);

        // Merge the current and next lists
        root = Merge(root, root.next);

        return root;
    }

    // Function to print the flattened linked list
    static void PrintList(Node head)
    {
        Node temp = head;

        while (temp != null) {
            Console.Write(temp.data);

            if (temp.bottom != null)
                Console.Write(" -> ");

            temp = temp.bottom;
        }

        Console.WriteLine();
    }

    static void Main()
    {
        // Create a hard-coded linked list:
        // 5 -> 10 -> 19 -> 28
        // |    |     |
        // 7    20    22
        // |          |
        // 8          50
        // |
        // 30

        Node head = new Node(5);
        head.bottom = new Node(7);
        head.bottom.bottom = new Node(8);
        head.bottom.bottom.bottom = new Node(30);

        head.next = new Node(10);
        head.next.bottom = new Node(20);

        head.next.next = new Node(19);
        head.next.next.bottom = new Node(22);
        head.next.next.bottom.bottom = new Node(50);

        head.next.next.next = new Node(28);

        head = flatten(head);

        PrintList(head);
    }
}
JavaScript
// Javascript program for flattening a Linked List

class Node {
    constructor(newData)
    {
        this.data = newData;
        this.next = null;
        this.bottom = null;
    }
}

// Utility function to merge two sorted linked lists
// using their bottom pointers
function merge(head1, head2)
{

    // A dummy first node to store the result list
    let dummy = new Node(-1);

    // Tail points to the last result node to add new nodes
    // to the result
    let tail = dummy;

    // Iterate till either head1 or head2 does not reach
    // null
    while (head1 !== null && head2 !== null) {
        if (head1.data <= head2.data) {

            // Append head1 to the result
            tail.bottom = head1;
            head1 = head1.bottom;
        }
        else {

            // Append head2 to the result
            tail.bottom = head2;
            head2 = head2.bottom;
        }

        // Move tail pointer to the next node
        tail = tail.bottom;
    }

    // Append the remaining nodes of non-null linked list
    if (head1 === null)
        tail.bottom = head2;
    else
        tail.bottom = head1;

    return dummy.bottom;
}

// Function to flatten the linked list
function flatten(root)
{

    // Base Cases
    if (root === null || root.next === null) {
        return root;
    }

    // Recur for next list
    root.next = flatten(root.next);

    // Now merge the current and next list
    root = merge(root, root.next);

    // Return the root
    return root;
}

function printList(node)
{
    while (node !== null) {
        process.stdout.write(node.data.toString());
        if (node.bottom !== null) {
            process.stdout.write(" -> ");
        }
        node = node.bottom;
    }
}

// Driver Code
/* Create a hard-coded linked list:
    5 -> 10 -> 19 -> 28
    |    |     |
    V    V     V
    7    20    22
    |          |
    V          V
    8          50
    |
    V
    30
*/

let head = new Node(5);
head.bottom = new Node(7);
head.bottom.bottom = new Node(8);
head.bottom.bottom.bottom = new Node(30);

head.next = new Node(10);
head.next.bottom = new Node(20);

head.next.next = new Node(19);
head.next.next.bottom = new Node(22);
head.next.next.bottom.bottom = new Node(50);

head.next.next.next = new Node(28);

head = flatten(head);
printList(head);

Output
5 -> 7 -> 8 -> 10 -> 19 -> 20 -> 22 -> 28 -> 30 -> 50

Time Complexity: O(n * n * m) - where n is the no of nodes in the main linked list and m is the no of nodes in a single sub-linked list. 

  • After adding the first 2 lists, the time taken will be O(m+m) = O(2m).
  • Then we will merge another list to above merged list -> time = O(2m + m) = O(3m).
  • We will keep merging lists to previously merged lists until all lists are merged.
  • Total time taken will be O(2m + 3m + 4m + .... n*m) = (2 + 3 + 4 + ... + n) * m = O(n * n * m)

[Better Approach] Sorting - O(n * m * log(n * m)) Time and O(n * m) Space

The idea is to traverse the linked list and push the values of all nodes into an array. Then, sort the array in ascending order and create a new linked list by traversing the sorted array.

Working of Approach:

  • Traverse the entire linked list using:
  • Outer loop -> move along the next pointer.
  • Inner loop -> move along the bottom pointer.
  • Push every node's data into the array.
  • After traversal, sort the array in ascending order.
  • Create a new linked list using the sorted array, connecting consecutive nodes through the bottom pointer.
  • Return the head of the newly created linked list — this is the flattened, sorted list.
C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

class Node
{
  public:
    int data;
    Node *next, *bottom;

    Node(int newdata)
    {
        data = newdata;
        next = bottom = nullptr;
    }
};

// function to flatten the linked list
Node *flatten(Node *root)
{

    vector<int> values;

    // Push values of all nodes into an array
    while (root != nullptr)
    {

        // Push the head node of the sub-linked-list
        values.push_back(root->data);

        // Push all the nodes of the sub-linked-list
        Node *temp = root->bottom;
        while (temp != nullptr)
        {
            values.push_back(temp->data);
            temp = temp->bottom;
        }

        // Move to the next head node
        root = root->next;
    }

    // Sort the node values in ascending order
    sort(values.begin(), values.end());

    // Construct the new flattened linked list
    Node *tail = nullptr;
    Node *head = nullptr;
    for (int i = 0; i < values.size(); i++)
    {
        Node *newNode = new Node(values[i]);

        // If this is the first node of the linked list,
        // make the node as head
        if (head == nullptr)
        {
            head = newNode;
        }
        else
        {
            tail->bottom = newNode;
        }
        tail = newNode;
    }
    return head;
}

void printList(Node *head)
{
    Node *temp = head;
    while (temp != nullptr)
    {
        cout << temp->data;
        if (temp->bottom)
            cout << " -> ";
        temp = temp->bottom;
    }
    cout << endl;
}

int main()
{

    // Create a hard-coded linked list:
    //   5 -> 10 -> 19 -> 28
    //   |    |     |
    //   V    V     V
    //   7    20    22
    //   |          |
    //   V          V
    //   8          50
    //   |
    //   V
    //   30

    Node *head = new Node(5);
    head->bottom = new Node(7);
    head->bottom->bottom = new Node(8);
    head->bottom->bottom->bottom = new Node(30);

    head->next = new Node(10);
    head->next->bottom = new Node(20);

    head->next->next = new Node(19);
    head->next->next->bottom = new Node(22);
    head->next->next->bottom->bottom = new Node(50);

    head->next->next->next = new Node(28);

    head = flatten(head);

    printList(head);
    return 0;
}
Java
import java.util.*;

class Node {
    int data;
    Node next, bottom;

    Node(int newData)
    {
        data = newData;
        next = bottom = null;
    }
}

class GFG {

    // Function to flatten the linked list
    static Node flatten(Node root)
    {
        List<Integer> values = new ArrayList<>();

        // Push values of all nodes into a list
        while (root != null) {
            // Push the head node of the sub-linked-list
            values.add(root.data);

            // Push all the nodes of the sub-linked-list
            Node temp = root.bottom;
            while (temp != null) {
                values.add(temp.data);
                temp = temp.bottom;
            }

            // Move to the next head node
            root = root.next;
        }

        // Sort the node values in ascending order
        Collections.sort(values);

        // Construct the new flattened linked list
        Node tail = null;
        Node head = null;
        for (int value : values) {
            Node newNode = new Node(value);

            // If this is the first node of the linked list,
            // make the node as head
            if (head == null)
                head = newNode;
            else
                tail.bottom = newNode;
            tail = newNode;
        }

        return head;
    }

    // Function to print the linked list
    static void printList(Node head)
    {
        Node temp = head;
        while (temp != null) {
            System.out.print(temp.data);
            if (temp.bottom != null)
                System.out.print(" -> ");
            temp = temp.bottom;
        }
        System.out.println();
    }

    public static void main(String[] args)
    {

        // Create a hard-coded linked list:
        // 5 -> 10 -> 19 -> 28
        // |    |     |
        // V    V     V
        // 7    20    22
        // |          |
        // V          V
        // 8          50
        // |
        // V
        // 30

        Node head = new Node(5);
        head.bottom = new Node(7);
        head.bottom.bottom = new Node(8);
        head.bottom.bottom.bottom = new Node(30);

        head.next = new Node(10);
        head.next.bottom = new Node(20);

        head.next.next = new Node(19);
        head.next.next.bottom = new Node(22);
        head.next.next.bottom.bottom = new Node(50);

        head.next.next.next = new Node(28);

        head = flatten(head);

        printList(head);
    }
}
Python
class Node:
    def __init__(self, new_data):
        self.data = new_data
        self.next = None
        self.bottom = None

# Function to flatten the linked list
def flatten(root):
    values = []

    # Push values of all nodes into an array
    while root is not None:
      
        # Push the head node of the sub-linked-list
        values.append(root.data)

        # Push all the nodes of the sub-linked-list
        temp = root.bottom
        while temp is not None:
            values.append(temp.data)
            temp = temp.bottom

        # Move to the next head node
        root = root.next

    # Sort the node values in ascending order
    values.sort()

    # Construct the new flattened linked list
    tail = None
    head = None
    for value in values:
        newNode = Node(value)

        # If this is the first node of the linked list,
        # make the node as head
        if head is None:
            head = newNode
        else:
            tail.bottom = newNode
        tail = newNode

    return head

def printList(node):
    while node is not None:
        print(f"{node.data}", end="")
        if node.next is not None:
            print(" -> ", end="")
        node = node.next
    print()

if __name__ == "__main__":
  
    # Create a hard-coded linked list:
    # 5 -> 10 -> 19 -> 28
    # |    |     |
    # V    V     V
    # 7    20    22
    # |          |
    # V          V
    # 8          50
    # |
    # V
    # 30
    head = Node(5)
    head.bottom = Node(7)
    head.bottom.bottom = Node(8)
    head.bottom.bottom.bottom = Node(30)

    head.next = Node(10)
    head.next.bottom = Node(20)

    head.next.next = Node(19)
    head.next.next.bottom = Node(22)
    head.next.next.bottom.bottom = Node(50)

    head.next.next.next = Node(28)

    head = flatten(head)

    printList(head)
C#
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node next, bottom;

    public Node(int newData)
    {
        data = newData;
        next = bottom = null;
    }
}

class GFG {
    // Function to flatten the linked list
    static Node flatten(Node root)
    {
        List<int> values = new List<int>();

        // Push values of all nodes into a list
        while (root != null) {
            values.Add(root.data);

            // Push all nodes of the sub-linked-list
            Node temp = root.bottom;
            while (temp != null) {
                values.Add(temp.data);
                temp = temp.bottom;
            }

            // Move to the next head node
            root = root.next;
        }

        // Sort node values in ascending order
        values.Sort();

        // Construct the new flattened linked list
        Node head = null;
        Node tail = null;

        foreach(int value in values)
        {
            Node newNode = new Node(value);

            if (head == null) {
                head = newNode;
            }
            else {
                tail.bottom = newNode;
            }

            tail = newNode;
        }

        return head;
    }

    // Function to print the flattened linked list
    static void PrintList(Node head)
    {
        Node temp = head;

        while (temp != null) {
            Console.Write(temp.data);
            if (temp.bottom != null)
                Console.Write(" -> ");

            temp = temp.bottom;
        }

        Console.WriteLine();
    }

    static void Main()
    {
        // Create the linked list
        // 5 -> 10 -> 19 -> 28
        // |    |     |
        // 7    20    22
        // |          |
        // 8          50
        // |
        // 30

        Node head = new Node(5);
        head.bottom = new Node(7);
        head.bottom.bottom = new Node(8);
        head.bottom.bottom.bottom = new Node(30);

        head.next = new Node(10);
        head.next.bottom = new Node(20);

        head.next.next = new Node(19);
        head.next.next.bottom = new Node(22);
        head.next.next.bottom.bottom = new Node(50);

        head.next.next.next = new Node(28);

        head = flatten(head);

        PrintList(head);
    }
}
JavaScript
class Node {
    constructor(newData)
    {
        this.data = newData;
        this.next = null;
        this.bottom = null;
    }
}

// Function to flatten the linked list
function flatten(root)
{
    let values = [];

    // Push values of all nodes into an array
    while (root !== null) {

        // Push the head node of the sub-linked-list
        values.push(root.data);

        // Push all the nodes of the sub-linked-list
        let temp = root.bottom;
        while (temp !== null) {
            values.push(temp.data);
            temp = temp.bottom;
        }

        // Move to the next head node
        root = root.next;
    }

    // Sort the node values in ascending order
    values.sort((a, b) => a - b);

    // Construct the new flattened linked list
    let head = null;
    let tail = null;
    for (let value of values) {
        let newNode = new Node(value);

        // If this is the first node of the linked list,
        // make the node as head
        if (head === null)
            head = newNode;
        else
            tail.bottom = newNode;
        tail = newNode;
    }
    return head;
}

// Function to print the linked list
function printList(node)
{
    while (node !== null) {
        process.stdout.write(node.data.toString());
        if (node.bottom !== null) {
            process.stdout.write(" -> ");
        }
        node = node.bottom;
    }
}

/* Create a hard-coded linked list:
    5 -> 10 -> 19 -> 28
    |    |     |
    V    V     V
    7    20    22
    |          |
    V          V
    8          50
    |
    V
    30
*/
let head = new Node(5);
head.bottom = new Node(7);
head.bottom.bottom = new Node(8);
head.bottom.bottom.bottom = new Node(30);

head.next = new Node(10);
head.next.bottom = new Node(20);

head.next.next = new Node(19);
head.next.next.bottom = new Node(22);
head.next.next.bottom.bottom = new Node(50);

head.next.next.next = new Node(28);

head = flatten(head);

printList(head);

Output
5 -> 7 -> 8 -> 10 -> 19 -> 20 -> 22 -> 28 -> 30 -> 50

[Expected Approach] Min-Heap - O(n * m * log(n)) Time and O(n) Space

The idea is to use a min-heap to store the head node of each sublist and repeatedly extract the smallest node to build the flattened sorted list.

Working of Approach:

  • Create a min-heap using a lambda comparator and push the head node of each sublist into it.
  • Use a dummy node to build the result list.
  • While the heap is not empty, extract the smallest node, append it to the result, set its next pointer to nullptr, and push its bottom node into the heap if it exists.
  • Set the last node's bottom pointer to nullptr and return dummy.bottom.
C++
#include <bits/stdc++.h>
using namespace std;

class Node
{
  public:
    int data;
    Node *next, *bottom;

    Node(int newdata)
    {
        data = newdata;
        next = bottom = nullptr;
    }
};

// Comparator for the min-heap
struct Compare
{
    bool operator()(Node *a, Node *b)
    {
        return a->data > b->data;
    }
};

// Function to flatten the linked list
Node *flatten(Node *head)
{
    if (head == nullptr)
        return nullptr;

    // Min-heap to store the current node of each sublist
    priority_queue<Node *, vector<Node *>, Compare> pq;

    // Push the head of every sublist into the heap
    while (head != nullptr)
    {
        pq.push(head);
        head = head->next;
    }

    // Dummy node to construct the flattened list
    Node dummy(-1);
    Node *tail = &dummy;

    // Process nodes in ascending order
    while (!pq.empty())
    {
        // Get the node with the smallest value
        Node *curr = pq.top();
        pq.pop();

        // Push the next node of the same sublist
        if (curr->bottom != nullptr)
            pq.push(curr->bottom);

        // Append the current node to the result
        tail->bottom = curr;
        tail = curr;

        // Remove the next pointer
        tail->next = nullptr;
    }

    // Mark the end of the flattened list
    tail->bottom = nullptr;

    return dummy.bottom;
}

int main()
{
    /*
        Create a hard-coded linked list:

        5 -> 10 -> 19 -> 28
        |    |     |
        V    V     V
        7    20    22
        |          |
        V          V
        8          50
        |
        V
        30
    */

    Node *head = new Node(5);
    head->bottom = new Node(7);
    head->bottom->bottom = new Node(8);
    head->bottom->bottom->bottom = new Node(30);

    head->next = new Node(10);
    head->next->bottom = new Node(20);

    head->next->next = new Node(19);
    head->next->next->bottom = new Node(22);
    head->next->next->bottom->bottom = new Node(50);

    head->next->next->next = new Node(28);

    head = flatten(head);

    // Print the flattened linked list
    auto printList = [](Node *head) {
        Node *temp = head;

        while (temp != nullptr)
        {
            cout << temp->data;

            if (temp->bottom != nullptr)
                cout << " -> ";

            temp = temp->bottom;
        }

        cout << endl;
    };

    printList(head);

    return 0;
}
Java
import java.util.*;

class Node {
    int data;
    Node next, bottom;

    Node(int newdata)
    {
        data = newdata;
        next = bottom = null;
    }
}

public class GFG {

    // Comparator for the min-heap
    static class Compare implements Comparator<Node> {
        public int compare(Node a, Node b)
        {
            return Integer.compare(a.data, b.data);
        }
    }

    // Function to flatten the linked list
    static Node flatten(Node head)
    {
        if (head == null)
            return null;

        // Min-heap to store the current node of each
        // sublist
        PriorityQueue<Node> pq
            = new PriorityQueue<>(new Compare());

        // Push the head of every sublist into the heap
        while (head != null) {
            pq.offer(head);
            head = head.next;
        }

        // Dummy node to construct the flattened list
        Node dummy = new Node(-1);
        Node tail = dummy;

        // Process nodes in ascending order
        while (!pq.isEmpty()) {
            // Get the node with the smallest value
            Node curr = pq.poll();

            // Push the next node of the same sublist
            if (curr.bottom != null)
                pq.offer(curr.bottom);

            // Append the current node to the result
            tail.bottom = curr;
            tail = curr;

            // Remove the next pointer
            tail.next = null;
        }

        // Mark the end of the flattened list
        tail.bottom = null;

        return dummy.bottom;
    }

    public static void main(String[] args)
    {
        /*
            Create a hard-coded linked list:

            5 -> 10 -> 19 -> 28
            |    |     |
            V    V     V
            7    20    22
            |          |
            V          V
            8          50
            |
            V
            30
        */

        Node head = new Node(5);
        head.bottom = new Node(7);
        head.bottom.bottom = new Node(8);
        head.bottom.bottom.bottom = new Node(30);

        head.next = new Node(10);
        head.next.bottom = new Node(20);

        head.next.next = new Node(19);
        head.next.next.bottom = new Node(22);
        head.next.next.bottom.bottom = new Node(50);

        head.next.next.next = new Node(28);

        head = flatten(head);

        // Print the flattened linked list
        Node temp = head;

        while (temp != null) {
            System.out.print(temp.data);

            if (temp.bottom != null)
                System.out.print(" -> ");

            temp = temp.bottom;
        }

        System.out.println();
    }
}
Python
import heapq

class Node:
    def __init__(self, data):
        self.data = data
        self.next = None
        self.bottom = None

def flatten(head):
    if head is None:
        return None

    # Min-heap to store the current node of each list
    pq = []
    idx = 0

    # Push the head of every list into the heap
    while head is not None:
        heapq.heappush(pq, (head.data, idx, head))
        idx += 1
        head = head.next

    dummy = Node(-1)
    tail = dummy

    while pq:
        # Get the smallest node
        _, _, curr = heapq.heappop(pq)

        # Push the next node of the same list
        if curr.bottom is not None:
            heapq.heappush(pq, (curr.bottom.data, idx, curr.bottom))
            idx += 1

        # Append the current node to the result
        tail.bottom = curr
        tail = curr
        tail.next = None

    tail.bottom = None
    return dummy.bottom


if __name__ == "__main__":
    # Create the linked list
    head = Node(5)
    head.bottom = Node(7)
    head.bottom.bottom = Node(8)
    head.bottom.bottom.bottom = Node(30)

    head.next = Node(10)
    head.next.bottom = Node(20)

    head.next.next = Node(19)
    head.next.next.bottom = Node(22)
    head.next.next.bottom.bottom = Node(50)

    head.next.next.next = Node(28)

    head = flatten(head)

    # Print the flattened linked list
    temp = head
    while temp is not None:
        print(temp.data, end="")
        if temp.bottom is not None:
            print(" -> ", end="")
        temp = temp.bottom

    print()
C#
using System;
using System.Collections.Generic;

class Node {
    public int data;
    public Node next, bottom;

    public Node(int x)
    {
        data = x;
        next = bottom = null;
    }
}

class GFG {
    public Node flatten(Node head)
    {
        if (head == null)
            return null;

        // Min-heap to store the current node of each list
        var pq = new PriorityQueue<Node, int>();

        // Push the head of every list into the heap
        while (head != null) {
            pq.Enqueue(head, head.data);
            head = head.next;
        }

        Node dummy = new Node(-1);
        Node tail = dummy;

        while (pq.Count > 0) {
            // Get the smallest node
            Node curr = pq.Dequeue();

            // Push the next node of the same list
            if (curr.bottom != null)
                pq.Enqueue(curr.bottom, curr.bottom.data);

            // Append the current node to the result
            tail.bottom = curr;
            tail = curr;
            tail.next = null;
        }

        tail.bottom = null;
        return dummy.bottom;
    }
}

class Program {
    static void Main()
    {
        /*
            Create a hard-coded linked list:

            5 -> 10 -> 19 -> 28
            |    |     |
            V    V     V
            7    20    22
            |          |
            V          V
            8          50
            |
            V
            30
        */

        Node head = new Node(5);
        head.bottom = new Node(7);
        head.bottom.bottom = new Node(8);
        head.bottom.bottom.bottom = new Node(30);

        head.next = new Node(10);
        head.next.bottom = new Node(20);

        head.next.next = new Node(19);
        head.next.next.bottom = new Node(22);
        head.next.next.bottom.bottom = new Node(50);

        head.next.next.next = new Node(28);

        GFG sol = new GFG();
        head = sol.flatten(head);

        // Print the flattened linked list
        Node temp = head;

        while (temp != null) {
            Console.Write(temp.data);

            if (temp.bottom != null)
                Console.Write(" -> ");

            temp = temp.bottom;
        }

        Console.WriteLine();
    }
}
JavaScript
class Node {
    constructor(data)
    {
        this.data = data;
        this.next = null;
        this.bottom = null;
    }
}

// Function to flatten the linked list
function flatten(head)
{
    if (head === null)
        return null;

    // Min-heap to store the current node of each list
    const pq = [];

    // Insert a node into the min-heap
    function push(node)
    {
        pq.push(node);
        let i = pq.length - 1;

        while (i > 0) {
            let parent = Math.floor((i - 1) / 2);

            if (pq[parent].data <= pq[i].data)
                break;

            [pq[parent], pq[i]] = [ pq[i], pq[parent] ];
            i = parent;
        }
    }

    // Remove and return the smallest node
    function pop()
    {
        const result = pq[0];
        const last = pq.pop();

        if (pq.length > 0) {
            pq[0] = last;
            let i = 0;

            while (true) {
                let smallest = i;
                let left = 2 * i + 1;
                let right = 2 * i + 2;

                if (left < pq.length
                    && pq[left].data < pq[smallest].data)
                    smallest = left;

                if (right < pq.length
                    && pq[right].data < pq[smallest].data)
                    smallest = right;

                if (smallest === i)
                    break;

                [pq[i], pq[smallest]] =
                    [ pq[smallest], pq[i] ];
                i = smallest;
            }
        }

        return result;
    }

    // Push the head of every list into the heap
    while (head !== null) {
        push(head);
        head = head.next;
    }

    const dummy = new Node(-1);
    let tail = dummy;

    while (pq.length > 0) {
        // Get the smallest node
        const curr = pop();

        // Push the next node of the same list
        if (curr.bottom !== null)
            push(curr.bottom);

        // Append the current node to the result
        tail.bottom = curr;
        tail = curr;
        tail.next = null;
    }

    tail.bottom = null;
    return dummy.bottom;
}

// Driver Code
//  Create the linked list
let head = new Node(5);
head.bottom = new Node(7);
head.bottom.bottom = new Node(8);
head.bottom.bottom.bottom = new Node(30);

head.next = new Node(10);
head.next.bottom = new Node(20);

head.next.next = new Node(19);
head.next.next.bottom = new Node(22);
head.next.next.bottom.bottom = new Node(50);

head.next.next.next = new Node(28);

head = flatten(head);

// Print the flattened linked list
let temp = head;
let result = [];

while (temp !== null) {
    result.push(temp.data);
    temp = temp.bottom;
}

console.log(result.join(" -> "));

Output
5 -> 7 -> 8 -> 10 -> 19 -> 20 -> 22 -> 28 -> 30 -> 50
Comment