Given a linked list where every node has two pointers, next and bottom, flatten the structure into one sorted linked list using the bottom pointer.
Each vertical chain connected through bottom is sorted in non-decreasing order. The final list must contain all nodes in sorted order, with next pointers removed or ignored.
Example 1
Input: [[5, 7, 8, 30], [10, 20], [19, 22, 50], [28, 35, 40, 45]]
Output: [5, 7, 8, 10, 19, 20, 22, 28, 30, 35, 40, 45, 50]
Explanation: Every vertical sorted list contributes values to one sorted bottom-linked chain.
Example 2
Input: [[7], [8], [30]]
Output: [7, 8, 30]
Explanation: Single-node vertical chains flatten in sorted order.
Brute Force Approach
In this approach, we ignore the existing sorted structure of the linked list and collect all node values into an array. We traverse each horizontal node using the next pointer and, for every such node, traverse its vertical chain using the bottom pointer.
After collecting all values, we sort the array in non-decreasing order. Then, we create a new linked list using only the bottom pointers and insert the sorted values one by one.
Algorithm
Create an empty array to store all node values, as collecting the values in one place makes it possible to sort them without depending on the existing linked-list structure.
Traverse the horizontal linked list using the
nextpointer, since each horizontal node represents the starting point of a separate vertical chain.For every horizontal node, traverse its vertical chain using the
bottompointer, so every node across all vertical lists is included.Append each visited node's value to the array, ensuring that no value from any vertical chain is missed.
Sort the array in non-decreasing order, as the final bottom-linked list needs to contain values from smallest to largest.
Create a new linked list using the sorted values and connect the nodes through the
bottompointer, since the required output uses the bottom links to represent the sorted chain.Return the head of the newly created bottom-linked list, as it represents the complete sorted structure.
Dry Run
flatten linkedlist
Solution
#include <bits/stdc++.h>using namespace std;struct Node { int data; Node* next; Node* bottom; Node(int value) { data = value; next = nullptr; bottom = nullptr; }};class Solution {public: // Function to flatten the linked list by collecting, // sorting, and rebuilding all node values. Node* flatten(Node* root) { // Store every node value from all bottom chains. vector<int> values; // Traverse each vertical linked list. Node* horizontal = root; while (horizontal != nullptr) { Node* vertical = horizontal; // Collect values from the current bottom chain. while (vertical != nullptr) { values.push_back(vertical->data); vertical = vertical->bottom; } // Move to the next vertical linked list. horizontal = horizontal->next; } // Sort all collected values. sort(values.begin(), values.end()); // Dummy node simplifies building the final bottom chain. Node dummy(0); Node* tail = &dummy; // Create a new sorted bottom linked list. for (int value : values) { tail->bottom = new Node(value); // Advance the tail after attaching the new node. tail = tail->bottom; } // Return the head of the flattened linked list. return dummy.bottom; }};// Function to build the linked list from multiple vertical lists.Node* buildList(vector<vector<int>>& lists) { // Dummy node simplifies horizontal list construction. Node dummy(0); Node* horizontalTail = &dummy; // Build each vertical linked list. for (auto& list : lists) { Node* verticalHead = nullptr; Node* verticalTail = nullptr; for (int value : list) { Node* node = new Node(value); // Initialize the vertical list. if (verticalHead == nullptr) { verticalHead = node; } // Append the node at the bottom. else { verticalTail->bottom = node; } // Update the vertical tail. verticalTail = node; } // Attach the completed vertical list horizontally. horizontalTail->next = verticalHead; // Advance to the newly attached list. horizontalTail = horizontalTail->next; } return dummy.next;}// Function to print the flattened bottom linked list.void printFlattened(Node* head) { while (head != nullptr) { cout << head->data; if (head->bottom != nullptr) { cout << " "; } head = head->bottom; }}// Driver code.int main() { vector<vector<int>> lists = { {5, 7, 8, 30}, {10, 20}, {19, 22, 50}, {28, 35, 40, 45} }; // Build the multi-level linked list. Node* root = buildList(lists);Complexity Analysis
Time Complexity: O(T log T) T is the total number of nodes across all vertical chains. We traverse all T nodes and then sort their values, which takes O(T log T).
Space Complexity: O(T) The array stores all T node values, and the newly created flattened list also contains T nodes.
Optimal Approach
Since every vertical chain is already sorted, we can use a min heap to always pick the smallest available node among all chains. Initially, we push the head node of every vertical chain into the heap.
Each time, we remove the smallest node from the heap and attach it to the flattened list using the bottom pointer. If the removed node has a bottom child, we push that child into the heap because it may be the next smallest candidate.
This works like merging multiple sorted linked lists and avoids sorting all values together.
Algorithm
Create a min heap ordered by node values, as it keeps the smallest currently available node at the top.
Traverse the horizontal
nextchain and push every top-level node into the heap, since each one represents the first available node of a sorted vertical chain.Create a dummy node and a
tailpointer for the flattened bottom-linked list, as the dummy node simplifies attaching the first node.While the heap is not empty, remove the node with the smallest value, since it is the next smallest node among all currently available candidates.
Attach the removed node to
tailusing thebottompointer and movetailforward, which extends the flattened list in sorted order.If the removed node has a
bottomchild, push it into the heap, as this child is the next available node from that vertical chain.Continue until the heap becomes empty, ensuring every node has been placed in non-decreasing order.
Set
tail->bottomtoNULL, as the final node should mark the end of the flattened list.Return
dummy->bottomas the head of the flattened list, since the dummy node is only used to simplify construction.
Dry Run
flatten a ll
Solution
#include <bits/stdc++.h>using namespace std;struct Node { int data; Node* next; Node* bottom; // Constructor for a linked list node. Node(int value) { data = value; next = nullptr; bottom = nullptr; }};class Solution {public: // Function to flatten the linked list using a min heap. Node* flatten(Node* root) { // Compare nodes by value so the smallest node stays on top. auto compare = [](Node* first, Node* second) { return first->data > second->data; }; // Store the current smallest node from every vertical list. priority_queue<Node*, vector<Node*>, decltype(compare)> minHeap(compare); // Traverse the horizontal chain. Node* horizontal = root; while (horizontal != nullptr) { // Add the head of the current vertical list to the heap. minHeap.push(horizontal); // Move to the next vertical list. horizontal = horizontal->next; } // Dummy node simplifies construction of the flattened list. Node dummy(0); Node* tail = &dummy; // Process nodes until every vertical list is exhausted. while (!minHeap.empty()) { // Extract the smallest available node. Node* smallest = minHeap.top(); minHeap.pop(); // Add the next node from the same vertical chain. if (smallest->bottom != nullptr) { minHeap.push(smallest->bottom); } // Attach the smallest node to the flattened bottom chain. tail->bottom = smallest; // Move the tail to the newly attached node. tail = tail->bottom; // Remove the old horizontal connection. tail->next = nullptr; } // Return the head of the flattened linked list. return dummy.bottom; }};// Function to build the linked list from multiple vertical arrays.Node* buildList(vector<vector<int>>& lists) { // Dummy node simplifies horizontal list construction. Node dummy(0); Node* horizontalTail = &dummy; // Build every vertical linked list. for (auto& list : lists) { Node* verticalHead = nullptr; Node* verticalTail = nullptr; for (int value : list) { Node* node = new Node(value); // Initialize the current vertical linked list. if (verticalHead == nullptr) { verticalHead = node; } else { // Attach the node at the bottom of the current list. verticalTail->bottom = node; } // Update the vertical tail. verticalTail = node; } // Attach the completed vertical list horizontally. horizontalTail->next = verticalHead; // Move to the newly attached vertical list. horizontalTail = horizontalTail->next; } // Return the first horizontal node. return dummy.next;}// Function to print the flattened bottom linked list.void printFlattened(Node* head) { while (head != nullptr) { cout << head->data; if (head->bottom != nullptr) { cout << " "; } // Move to the next node in the bottom chain. head = head->bottom; }}Complexity Analysis
Time Complexity: O(T log K) T is the total number of nodes, and K is the number of vertical chains. Each node is processed once through a min heap containing at most K nodes.
Space Complexity: O(K) The min heap stores at most one active node from each of the K vertical chains.
FAQs about Flattening of Linked List
Q1. Can flattening be done without creating new nodes?
Yes. Heap-based and pairwise merge approaches can reuse existing nodes and reconnect nodes through bottom pointers.
Q2. Which pointer should form the final flattened list?
The final sorted chain should use the bottom pointer, while next pointers should be cleared or ignored.
Q3. Does the min heap approach preserve sorted order?
Yes. The heap always extracts the smallest current node among all active vertical chains.
Be the first to add a comment.