LeetCode

Add two numbers

given 2 reviersed linked list add provide the result

mediumtime: O(n)space: O(n)lang: Java
linked list

Problem

You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.

Complexity

  • Time: O(n)
  • Space: O(1)

Solution (Java)

 
public class AddTwoNumbers {
    /**
     * Orchestrator only.
     * Contract:
     * - Input: two non-null reverse-order digit lists (0..9 per node).
     * - Output: new reverse-order digit list representing their sum.
     * Side effects:
     * - Does not mutate l1/l2; allocates result nodes.
     * Complexity: O(n+m) time, O(n+m) output space.
     */
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        validateInputs(l1, l2);
 
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
 
        ListNode p1 = l1;
        ListNode p2 = l2;
        int carry = 0;
 
        while (shouldContinue(p1, p2, carry)) {
            int aDigit = readDigit(p1);
            int bDigit = readDigit(p2);
 
            int[] step = addDigitsWithCarry(aDigit, bDigit, carry); // [outDigit, carryOut]
 
            tail = appendNode(tail, step[0]);
 
            p1 = advance(p1);
            p2 = advance(p2);
            carry = step[1];
        }
 
        return finalizeResult(dummy);
    }
 
    // ------------------------------------------------------------
    // SUBSYSTEM: validateInputs
    // Contract: throws IllegalArgumentException if inputs are invalid.
    // Invariants: does not mutate input lists.
    // Time: O(n+m) worst-case for a full traversal; O(1) here since
    //       LeetCode guarantees valid nodes (we just null-check).
    // Space: O(1).
    // ------------------------------------------------------------
    static void validateInputs(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null) {
            throw new  IllegalArgumentException("Input lists cannot be null");
        }
    }
 
    // ------------------------------------------------------------
    // SUBSYSTEM: readDigit
    // Contract: returns node.val if node != null, else 0.
    // Invariants: return value is always in [0..9].
    // Time: O(1), Space: O(1).
    // ------------------------------------------------------------
    static int readDigit(ListNode node) {
        if(node == null) {
            return 0;
        } else {
            return node.val;
        }
    }
 
    // ------------------------------------------------------------
    // SUBSYSTEM: readDigit
    // Contract: returns node.val if node != null, else 0.
    // Invariants: return value is always in [0..9].
    // Time: O(1), Space: O(1).
    // ------------------------------------------------------------
    static ListNode advance(ListNode node) {
        if(node == null) {
            return null;
        } else {
            return node.next;
        }
    }
 
    // ------------------------------------------------------------
    // SUBSYSTEM: addDigitsWithCarry
    // Contract:
    //   - Inputs: aDigit in [0..9], bDigit in [0..9], carryIn in [0..1].
    //   - Output: int[]{outDigit (0..9), carryOut (0..1)}.
    // Invariant: aDigit + bDigit + carryIn == outDigit + 10 * carryOut.
    // Time: O(1), Space: O(1).
    // ------------------------------------------------------------
    static int[] addDigitsWithCarry(int aDigit, int bDigit, int carryIn) {
        int total = aDigit + bDigit + carryIn;
        int outDigit = total % 10;
        int carryout = total / 10;
        return new int[]{outDigit, carryout};
    }
 
    // ------------------------------------------------------------
    // SUBSYSTEM: appendNode
    // Contract:
    //   - Allocates a new ListNode with the given digit.
    //   - Links it after the current tail and returns the new tail.
    // Invariants: tail.next is set; new tail is the appended node;
    //             original list structure is not altered.
    // Time: O(1), Space: O(1) auxiliary (one node allocated).
    // ------------------------------------------------------------
    static ListNode appendNode(ListNode tail, int digit) {
        ListNode newNode = new ListNode(digit);
        tail.next = newNode;
        return newNode;
    }
 
    // ------------------------------------------------------------
    // SUBSYSTEM: shouldContinue
    // Contract:
    //   - Returns true if there is remaining work:
    //       any unread input node OR a non-zero carry.
    //   - Returns false only when both lists are exhausted AND carry is 0.
    // Invariants: loop terminates; no side effects.
    // Time: O(1), Space: O(1).
    // ------------------------------------------------------------
    static boolean shouldContinue(ListNode p1, ListNode p2, int carry) {
        if(p1 != null || p2 != null || carry != 0) {
            return true;
        } else {
            return false;
        }
    }
 
    // ------------------------------------------------------------
    // SUBSYSTEM: finalizeResult
    // Contract:
    //   - Discards the dummy head and returns the real first node.
    //   - If result would be empty (should not happen by problem
    //     constraints), returns a node representing 0.
    // Invariants: does not mutate the result list.
    // Time: O(1), Space: O(1).
    // ------------------------------------------------------------
    static ListNode finalizeResult(ListNode dummyHead) {
        if(dummyHead.next == null) {
            return new ListNode(0);
        } else {
            return dummyHead.next;
        }
    }
 
 
    public static void main(String[] args) {
        AddTwoNumbers solution = new AddTwoNumbers();
 
        // Example test case: (2 -> 4 -> 3) + (5 -> 6 -> 4) = (7 -> 0 -> 8)
        ListNode l1 = new ListNode(2, new ListNode(4, new ListNode(3)));
        ListNode l2 = new ListNode(5, new ListNode(6, new ListNode(4)));
        ListNode result = solution.addTwoNumbers(l1, l2);
 
        // Print the result list
        while (result != null) {
            System.out.print(result.val);
            if (result.next != null) {
                System.out.print(" -> ");
            }
            result = result.next;
        }
    }
}