Skip to main content

2. Add Two Numbers

mediumAsked at Apple

Add Two Numbers is Apple's linked-list-as-digits arithmetic question. Walk both lists in parallel, adding digit + digit + carry, allocate a new node per output digit, and handle different lengths and a possible trailing carry. The dummy-head trick keeps the code tidy.

By Alex Chen, Founder, InterviewChamp.AI · Last verified

Source citations

Public interview reports confirming this problem appears in Apple loops.

  • Glassdoor (2026-Q1)Apple SWE phone-screen reports list Add Two Numbers as a recurring 30-minute linked-list arithmetic medium.
  • Blind (2025-12)Apple ICT3/ICT4 reports cite Add Two Numbers with the 'what if reversed?' (LC 445) follow-up.

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. You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Constraints

  • The number of nodes in each linked list is in the range [1, 100].
  • 0 <= Node.val <= 9
  • It is guaranteed that the list represents a number that does not have leading zeros.

Examples

Example 1

Input
l1 = [2,4,3], l2 = [5,6,4]
Output
[7,0,8]

Explanation: 342 + 465 = 807.

Example 2

Input
l1 = [0], l2 = [0]
Output
[0]

Example 3

Input
l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
Output
[8,9,9,9,0,0,0,1]

Approaches

1. Parallel walk with carry (optimal)

Allocate dummy head. Walk both lists in lockstep; at each step, sum = l1.val + l2.val + carry (treating missing values as 0). Push sum % 10 as new node, update carry = sum / 10. Loop until both null AND carry is 0.

Time
O(max(n, m))
Space
O(max(n, m)) for the output
function addTwoNumbers(l1, l2) {
  const dummy = { val: 0, next: null };
  let tail = dummy;
  let carry = 0;
  while (l1 || l2 || carry) {
    const v1 = l1 ? l1.val : 0;
    const v2 = l2 ? l2.val : 0;
    const sum = v1 + v2 + carry;
    tail.next = { val: sum % 10, next: null };
    tail = tail.next;
    carry = Math.floor(sum / 10);
    if (l1) l1 = l1.next;
    if (l2) l2 = l2.next;
  }
  return dummy.next;
}

Tradeoff: Single pass, allocates one new node per output digit. The 'while l1 OR l2 OR carry' is the trick — handles different lengths and the trailing carry case (999 + 1 = 1000) in one loop condition.

2. Convert to numbers, add, build list

Walk each list to build the integer; sum; build a new reverse-digit list.

Time
O(n + m)
Space
O(max(n, m))
function addTwoNumbers(l1, l2) {
  function toBig(list) {
    let s = '';
    while (list) { s = list.val + s; list = list.next; }
    return BigInt(s);
  }
  let sum = toBig(l1) + toBig(l2);
  if (sum === 0n) return { val: 0, next: null };
  const dummy = { val: 0, next: null };
  let tail = dummy;
  while (sum > 0n) {
    tail.next = { val: Number(sum % 10n), next: null };
    tail = tail.next;
    sum /= 10n;
  }
  return dummy.next;
}

Tradeoff: Works in any language with arbitrary precision (BigInt in JS). Apple's reject reason: 'the question is about linked-list arithmetic, not language-feature arithmetic — show me the digit-by-digit add.' Use only if asked for alternative.

Apple-specific tips

Apple's grade is on the loop condition. The naive version is 'while l1 and l2' — that misses the case where one list is longer or where a trailing carry needs to become a new node. The correct condition 'while l1 OR l2 OR carry' folds all three cases into one. Verbally name this BEFORE writing: 'I need to keep going as long as either list has digits left OR there's an unconsumed carry.'

Common mistakes

  • Loop condition 'while l1 and l2' — misses different-length and trailing-carry cases.
  • Forgetting to advance l1 and l2 only when they're non-null.
  • Returning dummy instead of dummy.next.

Follow-up questions

An interviewer at Apple may pivot to one of these next:

  • Add Two Numbers II (LC 445) — digits in FORWARD order; reverse both first or use stacks.
  • What if the lists could be arbitrarily long? Same algorithm, just don't try to convert to native int.
  • Multiply Strings (LC 43) — same digit-by-digit idea on strings.

Solve it now

Free. No sign-up. Python and JavaScript run instantly in your browser.

Output

Press Run or Cmd+Enter to execute

FAQ

Why does the carry need to be in the loop condition?

Consider 999 + 1 = 1000. The first three digits each produce a carry. After both lists are exhausted, there's still a carry of 1 that needs to become a new node.

What if both heads were 0?

The loop runs once (since carry starts at 0 but l1 and l2 are both non-null), produces a single 0 node, returns it. Correct.

Free learning resources

Curated free links for this problem.

Practice these live with InterviewChamp.AI

Drill Add Two Numbers and other Apple interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.

Practice these live with InterviewChamp.AI →