LeetCode ยท #1

Two Sum Solution

Given an array of integers and a target, return indices of the two numbers that add up to the target. Exactly one solution exists. You may not use the same element twice.

01
Section One ยท Problem

Problem Statement

๐Ÿท๏ธ

Difficulty

Easy

๐Ÿ”—

LeetCode

Problem #1

๐Ÿ—๏ธ

Pattern

Hash Map โ€” complement lookup

Given an array of integers nums and an integer target, return the indices of the two numbers that add up to target. Each input has exactly one solution, and you may not use the same element twice.

Example
Input: nums = [2, 7, 11, 15], target = 9 Output: [0, 1] // Because nums[0] + nums[1] = 2 + 7 = 9
Constraints
โ€ข 2 โ‰ค nums.length โ‰ค 10โด โ€ข -10โน โ‰ค nums[i] โ‰ค 10โน โ€ข -10โน โ‰ค target โ‰ค 10โน โ€ข Exactly one valid answer exists โ€ข You may not use the same element twice
02
Section Two ยท Approach 1

Brute Force โ€” O(nยฒ)

The most straightforward approach: for every element, scan the rest of the array looking for its complement. Two nested loops โ€” the outer picks the first number, the inner searches for target - nums[i].

Why it works

By checking every pair (i, j) where j > i, we guarantee we find the pair that sums to target. It's correct but slow โ€” O(nยฒ) comparisons.

Why we can do better
Problem: The inner loop repeats work. For each element, we ask "have I seen the complement before?" โ€” but we're scanning the array from scratch every time. A HashMap answers that question in O(1) instead of O(n).
Java โ€” Brute Force
public int[] twoSum(int[] nums, int target) { for (int i = 0; i < nums.length; i++) { for (int j = i + 1; j < nums.length; j++) { if (nums[i] + nums[j] == target) { return new int[] {i, j}; } } } return new int[] {}; // unreachable per constraints }
Python โ€” Brute Force
class Solution: def twoSum(self, nums: list[int], target: int) -> list[int]: for i in range(len(nums)): for j in range(i + 1, len(nums)): if nums[i] + nums[j] == target: return [i, j] return [] # unreachable
MetricValue
TimeO(nยฒ) โ€” every pair checked
SpaceO(1) โ€” no extra storage
03
Section Three ยท Approach 2

HashMap โ€” O(n)

The key insight: as we scan the array, we need to answer "have I already seen the number that would complete this pair?" โ€” that's a lookup problem. A HashMap maps each value to its index, giving O(1) lookups.

๐Ÿ’ก Mental model: Imagine you're at a party looking for your dance partner. Instead of walking up to every person and asking "are you the one?", you write your name and what you need on a whiteboard by the entrance. Each new guest checks the whiteboard first โ€” if their complement is already listed, it's a match. If not, they add themselves and walk in. That whiteboard is your HashMap.
Algorithm โ€” One-pass HashMap
  • Step 1: Create an empty HashMap<Integer, Integer> โ€” maps value โ†’ index.
  • Step 2: For each element nums[i], compute complement = target - nums[i].
  • Step 3: Check if complement exists in the map โ†’ if yes, return [map.get(complement), i].
  • Step 4: If not, store nums[i] โ†’ i in the map and continue.
๐ŸŽฏ When to recognize this pattern:
  • Any time a problem says "find two elements that satisfy condition X" โ€” especially sums, differences, or complements โ€” think HashMap complement lookup.
  • If you're scanning an array and asking "have I seen the other half before?", a HashMap turns that O(n) scan into O(1).
  • This pattern appears in Two Sum, Three Sum (as a sub-routine), pair-with-given-difference, and subarray-sum problems.
Why one pass works:
  • We store each element after checking for its complement.
  • This guarantees we never match an element with itself (the "don't use same element twice" constraint) โ€” because an element is only added to the map after it has been processed as a potential match.
  • When we find a complement, it must be a different, earlier element.
04
Section Four ยท Trace

Visual Walkthrough

Trace through nums = [2, 7, 11, 15], target = 9:

One-pass HashMap โ€” all 4 iterations
ARRAY 2 i=0 7 i=1 11 i=2 15 i=3 target = 9 Step 1 โ€” i=0, nums[i]=2 complement = 9 โˆ’ 2 = 7 map has 7? No โ†’ store map[2] = 0 map: { 2โ†’0 } Step 2 โ€” i=1, nums[i]=7 complement = 9 โˆ’ 7 = 2 map has 2? โœ“ YES โ†’ map.get(2) = 0 โ†’ return [0, 1] โœ“ โ€” DONE, exit early FOUND! indices [0, 1] โ€” what a full pass would look like (skipped here) โ€” Step 3 โ€” i=2, nums[i]=11 complement = 9 โˆ’ 11 = โˆ’2 map has โˆ’2? No โ†’ store map[11] = 2 map: { 2โ†’0, 7โ†’1, 11โ†’2 } Step 4 โ€” i=3, nums[i]=15 complement = 9 โˆ’ 15 = โˆ’6 map has โˆ’6? No โ†’ store map[15] = 3 map: { 2โ†’0, 7โ†’1, 11โ†’2, 15โ†’3 } Answer: [0, 1] โ†’ nums[0] + nums[1] = 2 + 7 = 9
Notice:
  • We found the answer on the second element. Steps 3 and 4 are greyed out โ€” they never execute.
  • In the best case, we find the pair early and exit.
  • In the worst case (answer at the end), we'd scan the entire array once building up the map โ€” still O(n).
05
Section Five ยท Implementation

Code โ€” Java & Python

Java โ€” One-pass HashMap
import java.util.HashMap; class Solution { public int[] twoSum(int[] nums, int target) { HashMap<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); // store value โ†’ index } return new int[] {}; // unreachable โ€” problem guarantees a solution } }
Python โ€” One-pass dict
class Solution: def twoSum(self, nums: list[int], target: int) -> list[int]: seen = {} # value โ†’ index for i, num in enumerate(nums): complement = target - num if complement in seen: return [seen[complement], i] seen[num] = i return [] # unreachable
06
Section Six ยท Analysis

Complexity Analysis

Approach Time Space Trade-off
Brute Force O(nยฒ) O(1) No extra memory, but too slow for n = 10โด
Sort + Two Pointers O(n log n) O(n) Need to track original indices (sort destroys them)
HashMap โ† optimal O(n) O(n) One pass, O(1) per lookup. Space for the map.
Why not sorting?:
  • Sorting would give O(n log n) time with two pointers โ€” but the problem asks for indices, not values.
  • Sorting destroys index information, so you'd need to store (value, originalIndex) pairs, adding complexity.
  • The HashMap approach is simpler, faster (O(n)), and directly returns indices.
07
Section Seven ยท Edge Cases

Edge Cases & Pitfalls

Case Input Why It Matters
Negative numbers [-1, -2, -3, -4, -5], target=-8 HashMap handles negatives โ€” complement lookup works the same way.
Zeros [0, 4, 3, 0], target=0 Two zeros sum to 0. One-pass ensures we find the second zero after storing the first โ†’ [0, 3].
Duplicate values [3, 3], target=6 We check for complement before storing โ€” so when we process the second 3, the first 3 is already in the map.
Minimum array [1, 2], target=3 Smallest valid input. Works correctly โ€” i=0 stores 1, i=1 finds complement 1 in map.
Large values [10โน, -10โน], target=0 No overflow risk โ€” we only do subtraction and comparison. Java int range handles ยฑ2ร—10โน.
โš  Common Mistake: Using a two-pass approach (build the full map first, then search) and accidentally matching an element with itself. One-pass avoids this: we store after checking, so an element can never be its own complement match.

โ† Back to Arrays & Hashing problems