Whiteboard interviews test more than problem-solving speed. They evaluate communication, clarity, and structured thinking. The REACTO method gives you a repeatable framework: Repeat, Examples, Approach, Code, Test, Optimize. Interviewers want to hear your reasoning out loud. A clean walkthrough with no answer beats a rushed solution with no explanation.
The Core Problem
Given an array of numbers and a target sum, determine if any two numbers in the array sum to the target. Return a boolean.
- Array [1, 2, 3, 9] with sum 8 → returns false (no valid pair)
- Array [1, 2, 4, 4] with sum 8 → returns true (4 + 4 = 8)
R. Repeat the Question
Input: an array of integers and a target sum. Output: a boolean. True if any two numbers add up to the target, false otherwise.
Clarifications to address out loud:
- Return the pair or just a boolean? → Boolean only
- Can numbers be negative or unordered? → Yes
- Can the same element be used twice? → No, must be two distinct indices
- What if the array is empty or has one element? → Return false
E. Example Cases
Before touching code, walk through examples with the interviewer. Confirm your understanding of edge cases. Empty array, single element, duplicates, negatives. This is where many candidates lose points by jumping too fast.
- [1, 2, 3, 9] target 8 → false
- [1, 2, 4, 4] target 8 → true (4 + 4)
- [-1, 5, 3] target 4 → true (-1 + 5)
- [] target 5 → false
- [5] target 5 → false (need two distinct elements)
A. Approach
Brute Force. O(n²)
Nested loops: for each element, check every other element. Simple to explain but doesn't scale. Mention this first. Interviewers appreciate knowing you understand the naive solution before optimizing.
Optimized. HashSet O(n)
Use a Set to track numbers seen so far. For each element, compute its complement (target minus current). If the complement is already in the Set, a valid pair exists. Otherwise, store the current number and continue. One pass through the array, O(1) lookup per step.
C. Code
function hasPairWithSum(arr: number[], sum: number): boolean {
const seen = new Set<number>();
for (const num of arr) {
const complement = sum - num;
if (seen.has(complement)) {
return true;
}
seen.add(num);
}
return false;
}
console.log(hasPairWithSum([1, 2, 3, 9], 8)); // false
console.log(hasPairWithSum([1, 2, 4, 4], 8)); // true
console.log(hasPairWithSum([-1, 5, 3], 4)); // trueT. Test Your Solution
Trace through the algorithm manually with [1, 2, 4, 4], sum=8:
- num=1: complement=7, not in seen. Add 1. seen={1}
- num=2: complement=6, not in seen. Add 2. seen={1,2}
- num=4: complement=4, not in seen. Add 4. seen={1,2,4}
- num=4: complement=4, IS in seen → return true
Now test an edge case: empty array. The loop never runs, returns false. Single element [5] with sum 10: one iteration, complement=5, seen is empty, adds 5, loop ends, returns false. Correct behavior.
O. Optimize and Discuss Tradeoffs
The HashSet solution is already O(n) time and O(n) space. If the interviewer asks about reducing space: a sorted array with two pointers achieves O(n log n) time and O(1) extra space, but only if the sort is in place. Array.prototype.sort in V8 is TimSort, which uses O(n) auxiliary memory and mutates the array you pass in, so sorting a copy puts you back at O(n) space. Which is better depends on the constraints. If the input is already sorted and memory is tight, two pointers wins.
// Two-pointer approach (requires sorted input)
function hasPairWithSumSorted(arr: number[], sum: number): boolean {
let left = 0;
let right = arr.length - 1;
while (left < right) {
const current = arr[left] + arr[right];
if (current === sum) return true;
if (current < sum) left++;
else right--;
}
return false;
}
// Input must be sorted
console.log(hasPairWithSumSorted([1, 2, 3, 9], 8)); // false
console.log(hasPairWithSumSorted([1, 2, 4, 4], 8)); // trueBonus: Streaming Data
An interviewer might extend the problem: what if the input is a stream instead of a finite array? You can apply the same HashSet logic using a generator, but with an important caveat: if no pair exists in the stream, the function never terminates. In an interview, naming this limitation explicitly shows maturity.
function hasPairWithSumStream(
stream: Iterable<number>,
sum: number,
limit = 10_000 // guard against infinite streams with no solution
): boolean {
const seen = new Set<number>();
let count = 0;
for (const num of stream) {
if (count++ >= limit) return false; // safety exit: false here means 'not found within limit'
const complement = sum - num;
if (seen.has(complement)) return true;
seen.add(num);
}
return false;
}
// Example: finite generator
function* numberStream(values: number[]) {
for (const v of values) yield v;
}
console.log(hasPairWithSumStream(numberStream([1, 2, 4, 4]), 8)); // trueRead that guard carefully, because it changes what the function means. Returning false after the limit says 'no pair exists', when all the code knows is 'no pair in the first 10,000 values'. That is a false negative, and it is the more interesting half of the trade-off. If the caller needs to tell those apart, return three states instead of a boolean: found, not found, limit reached. Naming what your safety exit costs you is worth more in an interview than the guard itself.
Key Concepts to Know Cold
Set. Stores unique values with average O(1) add and has operations, and say 'average' out loud, because hashing degrades in the worst case. More efficient than an array for membership checks. The core data structure behind this solution.
for...of. Iterates over any iterable (array, Set, generator output). No index management needed, works cleanly with generators.
Generator functions. Pause and resume execution using yield. Return an iterator that produces values on demand. Useful for simulating streams or lazy sequences. The key interview point: generators are lazy, but if there is no terminating condition and the problem has no solution, iteration never stops.
In an interview, the quality of your explanation is as valuable as the correctness of your code. Walk through the algorithm step by step, test your own solution out loud, and name the tradeoffs before the interviewer asks.
References
- MDN Web Docs. Set. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
- MDN Web Docs. Iterators and Generators. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_generators
- LeetCode. Two Sum (classic variant). https://leetcode.com/problems/two-sum/
- GeeksforGeeks. Two Sum, Pair with Given Sum. https://www.geeksforgeeks.org/dsa/check-if-pair-with-given-sum-exists-in-array/