Merge Two Sorted Lists In Reverse Order | 4 Solutions | Brute➡️Optimal | Self Explanatory Comments

😊 𝙎𝙚𝙡𝙛 𝘾𝙧𝙚𝙖𝙩𝙚𝙙 𝙇𝙤𝙜𝙞𝙘 ~ 𝙒𝙞𝙩𝙝 ❤️ 𝙗𝙮 𝙃𝙞𝙧𝙚𝙣

Given two linked lists of size N and M, which are sorted in non-decreasing order. The task is to merge them in such a way that the resulting list is in reverse order.

N = 4, M = 3
List1 = 5 -> 10 -> 15 -> 40
List2 = 2 -> 3 -> 20
Output: 40 -> 20 -> 15 -> 10 -> 5 -> 3 -> 2

Note: Hey There! Just Take A Look At The Code And Comments Within It. You'll Get It.
Note: Time Complexity And Auxiliary Space Is Mentioned With The Code.
Note: If You Have Any Kind Of Doubt, Just Comment And I'll Be There For You.

Approach 1 : Using Sorting With Buffer

// #1 Solution class:
class Solution_V1 {
    // Method helper
    static bool comparator(ListNode* node1, ListNode* node2) {
        return node1->val < node2->val;
    }
    
public:
    // Method to merge two sorted lists in reverse order, using sorting with buffer - O(NLogN + MLogM) & O(N+M) : Where N is the size of "list1" and M of "list2".
    ListNode* mergeTwoLists(ListNode* headNode1, ListNode* headNode2) {
        // Edge case: When both the lists are empty.
        if(!headNode1 && !headNode2)
            return nullptr;

        // Stores all the nodes of both the lists.
        vector<ListNode*> buffer;
        
        // Iterate the lists.
        while(headNode1 || headNode2) {
            // If the node of "list1" exist then store it to the buffer.
            if(headNode1)
                buffer.push_back(headNode1), headNode1 = headNode1->next;
            // If the node of "list2" exist then store it to the buffer.
            if(headNode2)
                buffer.push_back(headNode2), headNode2 = headNode2->next;
        }
        
        // Sort all the nodes based on their values.
        sort(begin(buffer), end(buffer), comparator);

        int size = buffer.size();
        
        // Iterate and link all the nodes of the buffer.
        for(int node = size-2; node >= 0; --node)
            buffer[node+1]->next = buffer[node];
        
        // If the buffer is not empty then set the last node of the "merge list".
        if(size > 0) 
            buffer[0]->next = nullptr;
        
        // If the buffer is not empty then return the head node of the "merge list".
        return (size > 0) ? buffer[size-1] : nullptr;
    }
};

Approach 2 : Using Buffer Only

// #2 Solution class:
class Solution_V2 {
public:
    // Method to merge two sorted lists in reverse order, using buffer only - O(N+M) & O(N+M) : Where N is the size of "list1" and M of "list2".
    ListNode* mergeTwoLists(ListNode* headNode1, ListNode* headNode2) {
        // Edge case: When both the lists are empty.
        if(!headNode1 && !headNode2)
            return nullptr;
        
        vector<ListNode*> list1; // Stores all the nodes of "list1".
        vector<ListNode*> list2; // Stores all the nodes of "list2".
        
        // Iterate the lists.
        while(headNode1 || headNode2) {
            // If the node of "list1" exist then store it to the corresponding buffer.
            if(headNode1)
                list1.push_back(headNode1), headNode1 = headNode1->next;
            // If the node of "list2" exist then store it to corresponding buffer.
            if(headNode2)
                list2.push_back(headNode2), headNode2 = headNode2->next;
        }

        // Set the "merge list" and return the head node of it.        
        return setMergeList(list1, list2);
    }
    
private:
    // Method helper
    ListNode* setMergeList(vector<ListNode*>& list1, vector<ListNode*>& list2) {
        int size1 = list1.size(), size2 = list2.size();
        int i = size1-1, j = size2-1;
        
        ListNode* resHead    = nullptr; // Tracks the head node of the "merge list".
        ListNode* resCurrent = nullptr; // Tracks the nodes of the "merge list".
        
        // Iterate the lists.
        while(i >= 0 && j >= 0) {
            // If the node value of "list1" is greater then set it to the "merge list".
            if(list1[i]->val > list2[j]->val) {
                updateLinks(i, list1, resHead, resCurrent);
                i--; 
            }
            // Else when the node value of "list2" is greater then set it to the "merge list".
            else {
                updateLinks(j, list2, resHead, resCurrent); 
                j--;
            }
        }
        
        // If the nodes of "list1" are remaining then set them to the "merge list".
        while(i >= 0) {
            updateLinks(i, list1, resHead, resCurrent);
            i--;
        }
        
        // If the nodes of "list2" are remaining then set them to the "merge list".
        while(j >= 0) {
            updateLinks(j, list2, resHead, resCurrent);
            j--;
        }
        
        // Return the head node of the "merge list".
        return resHead;
    }    
    
    // Method helper
    void updateLinks(int node, vector<ListNode*>& list, ListNode*& resHead, ListNode*& resCurrent) {
        // If the "merge list" is empty then set the head node of it.
        if(!resHead)
            resHead = list[node], resCurrent = list[node];
        // Else set the current node in the "merge list".
        else
            resCurrent->next = list[node], resCurrent = resCurrent->next;
        // Set the current node of the "merge list" as the last node of it.
        resCurrent->next = nullptr; 
    }
};

Approach 3 : Using Constant Auxiliary Space (Reversing The Input Lists)

// #3 Solution class:
class Solution_V3 {
public:
    // Method to merge two sorted lists in reverse order, using constant auxiliary space - O(N+M) & O(1) : Where N is the size of "list1" and M of "list2".
    ListNode* mergeTwoLists(ListNode* headNode1, ListNode* headNode2) {
        // Edge case: When both the lists are empty.
        if(!headNode1 && !headNode2)
            return nullptr;
            
        headNode1 = reverseList(headNode1); // Reverse the "list1" and store the head node of it.
        headNode2 = reverseList(headNode2); // Reverse the "list2" and store the head node of it.
        
        // Set the "merge list" and return the head node of it.
        return setMergeList(headNode1, headNode2);
    }
    
private:
    // Method helper
    ListNode* reverseList(ListNode* headNode) {
        ListNode* prevNode = nullptr;
        ListNode* currNode = headNode;
        
        while(currNode) {
            ListNode* nextNode = currNode->next;
            currNode->next = prevNode;
            prevNode = currNode;
            currNode = nextNode;
        }
        
        return prevNode;
    }

    // Method helper
    ListNode* setMergeList(ListNode* headNode1, ListNode* headNode2) {
        ListNode* nodeList1 = headNode1; // Tracks the nodes of "list1".
        ListNode* nodeList2 = headNode2; // Tracks the nodes of "list2".
        ListNode* resHead    = nullptr;  // Tracks the head node of the "merge list".
        ListNode* resCurrent = nullptr;  // Tracks the nodes of the "merge list".
        
        // Iterate the lists.
        while(nodeList1 && nodeList2) {
            ListNode* nextNode1 = nodeList1->next;
            ListNode* nextNode2 = nodeList2->next;
            // If the node value of "list1" is greater then set it to the "merge list".
            if(nodeList1->val > nodeList2->val) {
                updateLinks(nodeList1, resHead, resCurrent);
                nodeList1 = nextNode1;
            }
            // Else when the node value of "list2" is greater then set it to the "merge list".
            else {
                updateLinks(nodeList2, resHead, resCurrent);
                nodeList2 = nextNode2;
            }
        }
        
        // If the nodes of "list1" are remaining then set them to the "merge list".
        while(nodeList1) {
            ListNode* nextNode1 = nodeList1->next;
            updateLinks(nodeList1, resHead, resCurrent);
            nodeList1 = nextNode1;
        }
        
        // If the nodes of "list2" are remaining then set them to the "merge list".
        while(nodeList2) {
            ListNode* nextNode2 = nodeList2->next;
            updateLinks(nodeList2, resHead, resCurrent);
            nodeList2 = nextNode2;
        }
        
        // Return the head node of the "merge list".
        return resHead;
    }

    // Method helper
    void updateLinks(ListNode* givenNode, ListNode*& resHead, ListNode*& resCurrent) {
        // If the "merge list" is empty then set the head node of it.
        if(!resHead)
            resHead = givenNode, resCurrent = givenNode;
        // Else set the current node in the "merge list".
        else
            resCurrent->next = givenNode, resCurrent = resCurrent->next;
        // Set the current node of the "merge list" as the last node of it.
        resCurrent->next = nullptr; 
    }
};

Approach 4 : Using Constant Auxiliary Space (No Reversing Of Input Lists)

// #4 Solution class:
class Solution_V4 {
public:
    // Method to merge two sorted lists in reverse order, using constant auxiliary space - O(N+M) & O(1) : Where N is the size of "list1" and M of "list2".
    ListNode* mergeTwoLists(ListNode* headNode1, ListNode* headNode2) {
        // Edge case: When both the lists are empty.
        if(!headNode1 && !headNode2)
            return nullptr;
            
        ListNode* nodeList1 = headNode1; // Tracks the nodes of "list1".
        ListNode* nodeList2 = headNode2; // Tracks the nodes of "list2".
        ListNode* resHead    = nullptr;  // Tracks the head node of the "merge list".
        ListNode* resCurrent = nullptr;  // Tracks the nodes of the "merge list".
        
        // Iterate the lists.
        while(nodeList1 && nodeList2) {
            ListNode* nextNode1 = nodeList1->next;
            ListNode* nextNode2 = nodeList2->next;
            // If the node value of "list2" is greater then set it to the "merge list".
            if(nodeList1->val < nodeList2->val) {
                updateLinks(nodeList1, resHead, resCurrent);
                nodeList1 = nextNode1;
            }
            // Else when the node value of "list1" is greater then set it to the "merge list".
            else {
                updateLinks(nodeList2, resHead, resCurrent);
                nodeList2 = nextNode2;
            }
        }
        
        // If the nodes of "list1" are remaining then set them to the "merge list".
        while(nodeList1) {
            ListNode* nextNode1 = nodeList1->next;
            updateLinks(nodeList1, resHead, resCurrent);
            nodeList1 = nextNode1;
        }
        
        // If the nodes of "list2" are remaining then set them to the "merge list".
        while(nodeList2) {
            ListNode* nextNode2 = nodeList2->next;
            updateLinks(nodeList2, resHead, resCurrent);
            nodeList2 = nextNode2;
        }
        
        // Return the head node of the "merge list".
        return resHead;
    }
    
private:
    // Method helper
    void updateLinks(ListNode* givenNode, ListNode*& resHead, ListNode*& resCurrent) {
        resCurrent = givenNode;
        givenNode->next = resHead;
        resHead = givenNode;
    }
};

𝗨𝗣𝗩𝗢𝗧𝗘 𝗜𝗙 𝗬𝗢𝗨 𝗟𝗜𝗞𝗘 𝗧𝗛𝗘 𝗦𝗢𝗟𝗨𝗧𝗜𝗢𝗡 👍

Note: This solutions are created by myself after reading this post :)
Link: https://leetcode.com/discuss/interview-question/3226055/Merge-two-sorted-linked-lists-and-return-it-as-a-new-list

Comments (2)