Skip to content

1. Two Sum (Easy)

Problem

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume each input has exactly one solution, and you may not use the same element twice. You can return the answer in any order.

Example

  • nums = [2, 7, 11, 15], target = 9[0, 1]
  • nums = [3, 2, 4], target = 6[1, 2]
  • nums = [3, 3], target = 6[0, 1]

LeetCode 1 · Link · Easy

Try it yourself

idle

Starter code: this editor begins with intentional TODOs. Fill the function, run the embedded tests, then compare your solution with the worked approaches below.

Click Run Python to execute. First run downloads Python (~10 MB, cached after that).

Approach 1: Brute force, try every pair

Iterate all (i, j) pairs with i < j; return when nums[i] + nums[j] == target.

def two_sum(nums: list[int], target: int) -> list[int]:
n = len(nums) # L1: O(1)
for i in range(n): # L2: outer loop, n iterations
for j in range(i + 1, n): # L3: inner loop, up to n-i-1 iterations
if nums[i] + nums[j] == target: # L4: O(1) check
return [i, j] # L5: O(1) return
return []

Where the time goes, line by line

Variables: n = len(nums).

LinePer-call costTimes executedContribution
L1 (len)O(1)O(1)1O(1)O(1)
L2 (outer loop)O(1)O(1)nO(n)O(n)
L3, L4 (inner loop + check)O(1)O(1)up to n²/2O(n2)O(n²) ← dominates
L5 (return)O(1)O(1)1O(1)O(1)

The nested loops make this quadratic. For n = 10⁴, that’s ~50 million comparisons.

Complexity

  • Time: O(n2)O(n²), driven by L3/L4 (nested loops).
  • Space: O(1)O(1).
final class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
for i in 0..<nums.count {
for j in (i + 1)..<nums.count where nums[i] + nums[j] == target { return [i, j] }
}
return []
}
}

Approach 2: Sort with remembered indices + two pointers

Sort by value (keeping original indices), then use two pointers from both ends.

def two_sum(nums: list[int], target: int) -> list[int]:
indexed = sorted(enumerate(nums), key=lambda p: p[1]) # L1: O(n log n)
l, r = 0, len(indexed) - 1 # L2: O(1)
while l < r: # L3: loop, at most n iterations
s = indexed[l][1] + indexed[r][1] # L4: O(1) sum
if s == target: # L5: O(1) check
return sorted([indexed[l][0], indexed[r][0]]) # L6: O(1) (2-element sort)
if s < target: # L7: O(1)
l += 1 # L8: O(1)
else:
r -= 1 # L9: O(1)
return []

Where the time goes, line by line

Variables: n = len(nums).

LinePer-call costTimes executedContribution
L1 (sort)O(nlogn)O(n log n)1O(nlogn)O(n log n) ← dominates
L2 (init pointers)O(1)O(1)1O(1)O(1)
L3-L9 (two-pointer scan)O(1)O(1)at most nO(n)O(n)

The sort owns the total cost; the two-pointer scan is linear.

Complexity

  • Time: O(nlogn)O(n log n), driven by L1 (the sort).
  • Space: O(n)O(n), the indexed copy.

This is the right approach for LeetCode 167. Two Sum II (input already sorted), where it drops to O(n)O(n) time and O(1)O(1) space.

Try this approach:

idle
Click Run Python to execute. First run downloads Python (~10 MB, cached after that).
final class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
let indexed = nums.enumerated().map { ($0.element, $0.offset) }.sorted { $0.0 < $1.0 }
var left = 0, right = indexed.count - 1
while left < right {
let sum = indexed[left].0 + indexed[right].0
if sum == target { return [indexed[left].1, indexed[right].1].sorted() }
if sum < target { left += 1 } else { right -= 1 }
}
return []
}
}

Approach 3: Hash map in a single pass (optimal)

For each element x, look up its complement target - x in a hash map of elements seen so far. If it’s there, we’ve found the pair.

def two_sum(nums: list[int], target: int) -> list[int]:
seen = {} # L1: O(1), empty dict
for i, x in enumerate(nums): # L2: loop, n iterations
complement = target - x # L3: O(1) arithmetic
if complement in seen: # L4: O(1) average hash lookup
return [seen[complement], i] # L5: O(1) return
seen[x] = i # L6: O(1) average hash insert
return []

Where the time goes, line by line

Variables: n = len(nums).

LinePer-call costTimes executedContribution
L1 (init dict)O(1)O(1)1O(1)O(1)
L2 (loop)O(1)O(1)nO(n)O(n)
L3 (arithmetic)O(1)O(1)nO(n)O(n)
L4 (hash lookup)O(1)O(1) avgnO(n)O(n) ← dominates
L5 (return)O(1)O(1)1O(1)O(1)
L6 (hash insert)O(1)O(1) avgup to nO(n)O(n)

Every operation is O(1)O(1) average per iteration. One pass over n elements gives O(n)O(n) total.

Complexity

  • Time: O(n)O(n), driven by L4/L6 (hash operations per element).
  • Space: O(n)O(n). Hash map can hold up to n entries.

Try this approach:

idle
Click Run Python to execute. First run downloads Python (~10 MB, cached after that).
final class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var seen: [Int: Int] = [:]
for (index, value) in nums.enumerated() {
if let match = seen[target - value] { return [match, index] }
seen[value] = index
}
return []
}
}

Summary

ApproachTimeSpace
Brute forceO(n2)O(n²)O(1)O(1)
Sort + two pointersO(nlogn)O(n log n)O(n)O(n)
Hash mapO(n)O(n)O(n)O(n)

The hash-map approach is the canonical answer. It’s strictly better than sort on time and same on space. The sort variant is worth knowing because it generalizes to Two Sum II (sorted) and 3Sum.

Test cases

# Quick smoke tests, paste into a REPL or save as test_two_sum.py and run.
# Uses the canonical implementation (Approach 3: hash map).
def two_sum(nums: list[int], target: int) -> list[int]:
seen = {}
for i, x in enumerate(nums):
complement = target - x
if complement in seen:
return [seen[complement], i]
seen[x] = i
return []
def _run_tests():
assert two_sum([2, 7, 11, 15], 9) == [0, 1]
assert two_sum([3, 2, 4], 6) == [1, 2]
assert two_sum([3, 3], 6) == [0, 1]
assert two_sum([1, 2, 3, 4, 5], 9) == [3, 4]
# Single-pair array
assert two_sum([0, 4], 4) == [0, 1]
print("all tests pass")
if __name__ == "__main__":
_run_tests()
  • Arrays, input; two-pointer pattern on the sorted variant
  • Hash Tables, complement-lookup (the optimal pattern)
  • Hash Map Counting, the lookup table pattern for complements, frequencies, and seen items.
  • Array Scans, the linear pass habit of carrying just enough state while reading each item once.