Guide contents

1. Two Sum in Rust: three useful approaches

Given a list of integers and a target, return the indices of two values whose sum equals the target.

Start with the obvious solution

Checking every pair is easy to verify but takes O(n²) time:

fn two_sum_slow(nums: &[i32], target: i32) -> Option<(usize, usize)> {
    for left in 0..nums.len() {
        for right in left + 1..nums.len() {
            if nums[left] + nums[right] == target {
                return Some((left, right));
            }
        }
    }
    None
}

Trade memory for speed

As we scan, a HashMap records each value's index. For the current value, we ask whether its complement has already appeared.

use std::collections::HashMap;

fn two_sum(nums: &[i32], target: i32) -> Option<(usize, usize)> {
    let mut seen = HashMap::new();

    for (index, &value) in nums.iter().enumerate() {
        if let Some(&other_index) = seen.get(&(target - value)) {
            return Some((other_index, index));
        }
        seen.insert(value, index);
    }

    None
}

The expected time is O(n) and the extra space is O(n).

A small Rust detail

The pattern &value copies each i32 out of the iterator's reference. Likewise, Some(&other_index) extracts a copied usize. For non-Copy values, we would need to think more carefully about borrowing or cloning.