0

I stumbled upon an algorithm problem of which I want an optimised approach. Here goes,


Suppose I have a linked-list which is sorted. Each element of the linked list may have a down pointer which contains a List which is sorted too.

What is the best memory and time efficient way to merge such a list with the subsequent down list?


For eg,

1 -> 5 -> 10 -> 60 -> 100
     |    |     |  
     20   50   101
     |    |
     30   70

This should get converted to:

1 -> 5 -> 10 -> 20 -> 30 -> 50 -> 60 -> 70 -> 100 -> 101

Data structure for linked list:

Node {
  Node next;
  List down;
  Integer value;
}

Thanks in advance :)

  • I suggest "K-way merge" algorithms to sort multiple sorted lists: https://en.wikipedia.org/wiki/K-way_merge_algorithm – Stef Aug 14 '20 at 15:31
  • Also https://stackoverflow.com/questions/22055495/algorithm-to-merge-multiple-sorted-sequences-into-one-sorted-sequence-in-c – Stef Aug 14 '20 at 15:32

3 Answers3

0

The simplest and efficient enough would be scanning the whole 'main' list, unlinking each 'down list' and appending it to the main one, and finally natural-merge sorting the resulting list as a whole.

CiaPan
  • 8,142
  • 2
  • 18
  • 32
0

Idea:

Traverse through the original linked list and merge the linked lists of the elements accordingly.

This is a code written in c++, this is an iterative approach but you can also write similarly write the recursive approach which would, of course, look simple by no of lines, but not O(1). So, better use the iterative approach :

// same logic merging two sorted arrays
Node* merge(Node *head1, Node *head2) {

    struct Node *end = NULL;
    struct Node *start = NULL;
    
    // merge till one of the linked list is completely traversed
    while (head1 != 0 and head2 != 0) {
        if (head1->data <= head2->data) {
            if (end == NULL) {
                start = head1;
                end = start;
            }
            
            else {
                end->bottom = head1;
                end = end->bottom;
            }
            
            head1 = head1->bottom;
        }
        
        else {
            if (end == NULL) {
                start = head2;
                end = head2;
            }
            
            else {
                end->bottom = head2;
                end = end->bottom;
            }
            
            head2 = head2->bottom;
        }
    }
    
    // check for the remaining elements in linked list which was not traversed completely
    if (head1 != NULL) {
        end->bottom = head1;
    }
    else {
        end->bottom = head2;;
    }

    return start;
}


Node *flatten(Node *root)
{
    // base condition
    if (root == NULL || root->next == NULL) {
        return root;
    }
   

   // merge the linked list of elements accordingly
   Node *prev = root, *to = root->next;
   while (to != NULL) {
       prev = merge(prev, to);
       to = to->next;
   }
   
   return prev;
}

Sai Sreenivas
  • 1,620
  • 1
  • 5
  • 16
0

Here is the link to the solution : https://www.geeksforgeeks.org/flattening-a-linked-list/

Just to give you a brief idea of the post on this link: Start from leftmost node of list, and you need follow the merge step of Merge sort. This merge will happen between right node(right of 1 which is 5) down list, and down list( down of 1 which is null) of leftmost node.

You need to create a new flattened list, and add to this list the nodes after comparison between 2 lists.

Keep on moving forward in your main list after merging 2 down lists.

another_CS_guy
  • 632
  • 5
  • 5