Skip to main content
  1. posts/

LeetCode #2: Add Two Numbers

·520 words·3 mins
Coding Leetcode Python
Table of Contents

Description
#

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 contain a single digit. Add the two numbers and return it as a linked list.

You may assume the two numbers do not contain any leading zero, except the number 0 itself.

Example:

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

(From the Add Two Numbers problem description)

Solutions
#

Problem API
#

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

    def __str__(self):
        if self.next:
            return f"{self.val}{self.next}"
        else:
            return f"{self.val}"

Tests
#

The problem description can be validated by the following tests:

import os
import pytest

from supplemental import ListNode

# --- helper methods ---
def from_py(*digits):
    digits = list(digits)
    head_node = ListNode(digits.pop(0))
    n = head_node
    while digits:
            n.next = ListNode(digits.pop(0))
            n = n.next
    return head_node

def to_py(head):
    r = []
    while head:
        r.append(head.val)
        head = head.next
    return r


def test_transformer():
    """ Make sure that the test tooling works. """
    for test_value in [ [1], [1,2], [1,2,3] ]:
        head = from_py(*test_value)
        print(f"{test_value} ==> {head}")
        assert to_py(head) == test_value

# --- END helper methods ---

class BaseTestClass:
    def test_vector_from_spec_ok(self):
        a = from_py(2,4,3)
        b = from_py(5,6,4)

        assert to_py(self.addTwoNumbers(a, b)) == [7,0,8]

    def test_adding_zeros_ok(self):
        a = from_py(0)
        b = from_py(0)

        assert to_py(self.addTwoNumbers(a, b)) == [0]

    def test_adding_carry_ok(self):
        a = from_py(5)
        b = from_py(7)

        assert to_py(self.addTwoNumbers(a, b)) == [2,1]

    def test_different_lengths(self):
        a = from_py(1,8)
        b = from_py(0)

        assert to_py(self.addTwoNumbers(a, b)) == [1,8]

Solution 1: iterative \(O(n)\)
#

The simplest solution probably is to just iterate over both lists and add the digits. The only “edge” case is that the carry needs to be taken of.

Time complexity
\(O(n)\).
Space complexity
\(O(n)\).

from supplemental import ListNode

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        carry = 0
        head = None
        tail = None
        while l1 or l2:
            v1 = l1.val if l1 else 0
            v2 = l2.val if l2 else 0

            sum = v1 + v2 + carry
            digit = sum % 10
            carry = 1 if sum >= 10 else 0

            if head is None:
                head = ListNode(digit)
                tail = head
            else:
                tail.next = ListNode(digit)
                tail = tail.next

            if l1: l1 = l1.next
            if l2: l2 = l2.next
        if carry:
            tail.next = ListNode(carry)
        return head

Test Results
#

With the following test result:

============================= test session starts ==============================
platform linux -- Python 3.7.5, pytest-3.10.1, py-1.8.0, pluggy-0.12.0
benchmark: 3.2.2 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000)
rootdir: /home/jens/Documents/leetcode.com/002-add_two_numbers, inifile:
plugins: benchmark-3.2.2, profiling-1.7.0
collected 4 items

test_1a-solution.py ....                                                 [100%]

============================ slowest test durations ============================

(0.00 durations hidden.  Use -vv to show these durations.)
=========================== 4 passed in 0.03 seconds ===========================


Tests ran in 0.17746263899607584 seconds

Summary
#

Solution Correct Status Runtime Memory Language
#1, iterative Yes Accepted 64 ms, faster than 93,77% 12,6 MB, less than 100% Python3