Two Sum Problem Classic Hash Solution in DSA Rust - Time & Space Complexity
We want to understand how fast the Two Sum solution using a hash map runs as the input size grows.
Specifically, how does the time to find two numbers that add up to a target change when the list gets bigger?
Analyze the time complexity of the following code snippet.
use std::collections::HashMap;
fn two_sum(nums: &[i32], target: i32) -> Option<(usize, usize)> {
let mut map = HashMap::new();
for (i, &num) in nums.iter().enumerate() {
let complement = target - num;
if let Some(&j) = map.get(&complement) {
return Some((j, i));
}
map.insert(num, i);
}
None
}
This code finds two numbers in the list that add up to the target using a hash map for quick lookups.
- Primary operation: One loop over the input array.
- How many times: Exactly once for each element in the list.
- Inside the loop: Constant time hash map lookups and insertions.
As the list size grows, the number of steps grows roughly the same amount.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 lookups and inserts |
| 100 | About 100 lookups and inserts |
| 1000 | About 1000 lookups and inserts |
Pattern observation: The work grows linearly with the input size.
Time Complexity: O(n)
This means the time to find the two numbers grows in direct proportion to the size of the input list.
[X] Wrong: "Because there is a loop inside a loop, the time is O(n²)."
[OK] Correct: The code only has one loop; hash map lookups are fast and do not add extra loops, so the time stays linear.
Understanding this solution's time complexity helps you explain why hash maps speed up searching, a key skill in coding interviews.
"What if the input list was sorted and we used two pointers instead of a hash map? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of hash map
The hash map stores each number as a key and its index as the value for quick access.Step 2: Use hash map for complement lookup
For each number, we check if the complement (target - number) exists in the hash map to find the pair.Final Answer:
To store numbers and their indices for quick lookup -> Option DQuick Check:
Hash map stores number:index pairs [OK]
- Thinking hash map sorts the array
- Trying to store sums instead of indices
- Using hash map to reverse elements
Solution
Step 1: Identify mutable hash map declaration
To insert elements, the hash map must be mutable, so use 'let mut'.Step 2: Use full path or import HashMap
Using 'std::collections::HashMap::new()' is correct if HashMap is not imported.Final Answer:
let mut map = std::collections::HashMap::new(); -> Option BQuick Check:
Mutable hash map declaration requires 'mut' [OK]
- Forgetting 'mut' keyword for mutable map
- Using HashMap without importing or full path
- Declaring map immutable when insertions needed
fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut map = std::collections::HashMap::new();
for (i, &num) in nums.iter().enumerate() {
if let Some(&index) = map.get(&(target - num)) {
return vec![index as i32, i as i32];
}
map.insert(num, i);
}
vec![]
}
fn main() {
let result = two_sum(vec![2, 7, 11, 15], 9);
println!("{:?}", result);
}Solution
Step 1: Iterate and check complements
At i=0, num=2, map empty, insert (2,0). At i=1, num=7, complement=9-7=2 found at index 0.Step 2: Return indices of complement pair
Return vector with indices [0,1] as the pair sums to target 9.Final Answer:
[0, 1] -> Option CQuick Check:
Indices of 2 and 7 are [0,1] [OK]
- Returning indices in wrong order
- Not casting usize to i32 for return
- Returning empty vector when pair exists
fn two_sum(nums: Vec<i32>, target: i32) -> Vec<i32> {
let mut map = std::collections::HashMap::new();
for (i, num) in nums.iter().enumerate() {
if let Some(&index) = map.get(&(target - num)) {
return vec![index as i32, i as i32];
}
map.insert(num, i);
}
vec![]
}Solution
Step 1: Check key types in hash map
Keys are i32 values, but 'num' is a reference (&i32), so insert needs dereferenced value.Step 2: Fix insertion to use dereferenced num
Change 'map.insert(num, i);' to 'map.insert(*num, i);' to insert i32 key, matching get() key type.Final Answer:
Change 'num' to '*num' in map.insert to match key type -> Option AQuick Check:
Dereference num when inserting key [OK]
- Inserting reference instead of value as key
- Changing target arithmetic incorrectly
- Making map immutable causing insert error
[3, 3, 4, 5] and target 6, what will the Two Sum classic hash solution return and why?Solution
Step 1: Check pairs for target sum
The first element 3 at index 0 is inserted. At index 1, num=3, complement=6-3=3 found at index 0.Step 2: Return indices of first matching pair
Return [0,1] because these two 3's sum exactly to 6.Final Answer:
[0, 1] because the first two 3's sum to 6 -> Option AQuick Check:
First pair summing to target returned [OK]
- Choosing pairs that don't sum to target
- Ignoring duplicate values as valid pairs
- Returning empty vector incorrectly
Ready to prove it?
Pass the test and this pattern moves unknown
