Skip to main content

1. Two Sum

https://leetcode.com/problems/two-sum/description/

Definition

LList of integersNN Cardinality (size) of LTThe target sumiThe current iteration index\begin{align} L \coloneqq \text{List of integers}\\ N \coloneqq |N| \space \text{Cardinality (size) of L}\\ T \coloneqq \text{The target sum}\\ i \coloneqq \text{The current iteration index}\\ \end{align}

Intuition

The idea is to iterate LL and for each index ii we should look for another index jj that contains a complement C=L[j]C = L[j] so:

L[i]+C=TL[i]+L[j]=TL[i] + C = T \Rightarrow L[i] + L[j] = T

To find the complement we shall use a lookup table. We don't need to preprocess the list LL to build the lookup table, we can fill it while iterating the list.

For the current element L[i]L[i], look for an entry with value TL[i]T - L[i] in the lookup table which gives us an index jj or empty. If the entry exists, return the response [i,j][i, j], otherwise add the entry L[i]iL[i] \Rightarrow i to the lookup table and repeat the process.

Ilustration

Example array: [1, 2, 0, 4, 6]
Target sum: 5

1st iteration

At the first iteration, ii starts at index 0 and the lookup table is empty. The current element is L[i]=L[0]=1L[i] = L[0] = 1, so we should look for the complement C=T1=51=4C = T - 1 = 5 - 1 = 4 but the lookup table is empty, so we just add the current element to the lookup table and increment ii.

RowKeyValue
i
1
2
0
4
6

2nd iteration

The current element is L[i]=L[1]=2L[i] = L[1] = 2, so we should look for the complement C=T2=52=3C = T - 2 = 5 - 2 = 3 but there is no entry with key 33 in the table, so we just add the current element to the lookup table and increment ii.

RowKeyValue
110
i
1
2
0
4
6

3rd iteration

The current element is L[i]=L[2]=0L[i] = L[2] = 0, so we should look for the complement C=T0=50=5C = T - 0 = 5 - 0 = 5 but there is no entry with key 55 in the table, so we just add the current element to the lookup table and increment ii.

RowKeyValue
110
221
i
1
2
0
4
6

4th iteration

The current element is L[i]=L[3]=4L[i] = L[3] = 4, so we should look for the complement C=T4=54=1C = T - 4 = 5 - 4 = 1 ant it exists in the table at row 11 which gives us the index 00, so the answer is [0,i]=[0,3][0, i] = [0, 3]

RowKeyValue
110
221
302
i
1
2
0
4
6

Implementation

Click to reveal implementation
class Solution:
def twoSum(self, nums: list[int], target: int) -> list[int]:
visited_numbers: dict[int, int] = {}

for i, n in enumerate(nums):
complement_index = visited_numbers.get(target - n, None)

if complement_index is not None:
return [complement_index, i]

visited_numbers[n] = i

Tests

import pytest
from .solution import Solution


@pytest.mark.parametrize('numbers,target,expected', [
([0, 1], 1, [0, 1]),
([1, 2, 3], 5, [1, 2]),
])
def test_solution(numbers, target, expected):
result = Solution().twoSum(numbers, target)
assert result == expected

Time complexity

In the worst case, the complement will be found at the last index so we need to iterate all the input and fill/query N1N - 1 table elements. The iteration is O(n)O(n) and the insertions/queries takes O(1)O(1) time assuming no collisions. So, the final time complexity is O(n)O(n).

Space complexity

In the worst case we need to fill the table with N1N - 1 entries, so the space complexity is O(N)O(N).