Problem Statement

We are given two non-empty linked list representing two non-negative integers. The digits are stored in reverse order, and each node contains a single digit. We need to add the two numbers and return the sum as a linked list.

Examples

Example 1:

Input: List1 = [2, 4, 3], List2 = [5, 6, 4]
Result: sum = 807; List = [7, 0, 8]

Explanation: Since the digits are stored in reverse order, reverse the number first to get the original number and then add them as 342 + 465 = 807
image-85.png

Different Approaches

1️⃣ Elementary Math

Keep track of the carry using a variable and simulate digits-by-digits sum starting from the head of the list, which contains the least significant digit.

image-86.png

Algorithm:

  • Create a dummy node which is the head of new linked list.
  • Create a node temp, initialize it with dummy.
  • Initialize carry to 0.
  • Loop through lists l1 and l2 until you reach both ends, and until carry is present.
    • Set sum = l1.val + l2.val
    • Update carry = sum/10
    • Create a new node with the digit value of (sum%10) and set it to temp node's next, then advance temp node to next.
    • Advance both l1 and l2.
  • Return dummy's next node.

Code:

#include <iostream>
using namespace std;

// Definition of the ListNode structure
struct ListNode {
    int val;                // Value of the node
    ListNode *next;         // Pointer to the next node in the list
    // Constructor to initialize a node with a value
    ListNode(int x) : val(x), next(nullptr) {}
};

// Function to add two numbers represented as linked lists
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
    // Create a dummy node to simplify list construction
    ListNode* dummy = new ListNode(0);
    ListNode* current = dummy; // Pointer to track the current position in the result list
    int carry = 0;             // To handle carry-over during addition

    // Loop until both lists are fully traversed and there's no carry left
    while (l1 || l2 || carry) {
        int sum = carry;       // Start with the carry from the previous step
        
        // Add the value of the current node of l1 if it exists
        if (l1) {
            sum += l1->val;
            l1 = l1->next;     // Move to the next node in l1
        }
        
        // Add the value of the current node of l2 if it exists
        if (l2) {
            sum += l2->val;
            l2 = l2->next;     // Move to the next node in l2
        }
        
        carry = sum / 10;      // Compute the carry for the next digit
        current->next = new ListNode(sum % 10); // Create a new node for the current digit of the sum
        current = current->next;               // Move to the next position in the result list
    }

    return dummy->next;        // Return the head of the resulting list (skipping the dummy node)
}

// Utility function to print a linked list
void printList(ListNode* head) {
    while (head) {
        cout << head->val << " ";  // Print the value of the current node
        head = head->next;         // Move to the next node
    }
    cout << endl;
}

int main() {
    // Creating the first linked list: 2 -> 4 -> 3 (represents the number 342)
    ListNode* l1 = new ListNode(2);
    l1->next = new ListNode(4);
    l1->next->next = new ListNode(3);

    // Creating the second linked list: 5 -> 6 -> 4 (represents the number 465)
    ListNode* l2 = new ListNode(5);
    l2->next = new ListNode(6);
    l2->next->next = new ListNode(4);

    // Printing the input lists
    cout << "List 1: ";
    printList(l1);
    cout << "List 2: ";
    printList(l2);

    // Adding the two numbers represented by the linked lists
    ListNode* sumList = addTwoNumbers(l1, l2);

    // Printing the resulting sum list
    cout << "Sum: ";
    printList(sumList);

    return 0;
}

// Output
List 1: 2 4 3 
List 2: 5 6 4 
Sum: 7 0 8 

Complexity Analysis:

  • Time Complexity: O(max (m,n))
    • m and n represent the length of l1 and l2 respectively.
  • Space Complexity: O(max(m, n))
    • The length of the new lists is at most max(m, n) +1