Two Sum III - Data structure design
add/find with frequency map — find scans entries and checks complement, doubling check for x+x = target.
3 min read
design hash-map
Problem#
Design a data structure supporting add(number) and find(target) — find returns true iff there exist two stored values whose sum equals target.
Examples#
add(1); add(3); add(5); find(4)→true.find(7)→false.
Constraints#
- Up to
10^4adds and10^4finds; values fit in 32-bit int.
Approach#
Frequency map value → count. add increments. find iterates each key x, checks whether target - x exists; special-case when x == target - x and require count >= 2.
Solution#
class TwoSum { unordered_map<int,int> cnt;public: void add(int number) { ++cnt[number]; } bool find(int value) { for (auto& [x, c] : cnt) { int y = value - x; if (x == y) { if (c >= 2) return true; } else if (cnt.count(y)) return true; } return false; }};type TwoSum struct { cnt map[int]int}
func Constructor() TwoSum { return TwoSum{cnt: map[int]int{}}}
func (t *TwoSum) Add(number int) { t.cnt[number]++}
func (t *TwoSum) Find(value int) bool { for x, c := range t.cnt { y := value - x if x == y { if c >= 2 { return true } } else if _, ok := t.cnt[y]; ok { return true } } return false}from collections import Counter
class TwoSum: def __init__(self) -> None: self.cnt: Counter[int] = Counter()
def add(self, number: int) -> None: self.cnt[number] += 1
def find(self, value: int) -> bool: for x, c in self.cnt.items(): y = value - x if x == y: if c >= 2: return True elif y in self.cnt: return True return Falsevar TwoSum = function() { this.cnt = new Map();};
TwoSum.prototype.add = function(number) { this.cnt.set(number, (this.cnt.get(number) || 0) + 1);};
TwoSum.prototype.find = function(value) { for (const [x, c] of this.cnt) { const y = value - x; if (x === y) { if (c >= 2) return true; } else if (this.cnt.has(y)) { return true; } } return false;};class TwoSum { private Map<Integer, Integer> cnt;
public TwoSum() { cnt = new HashMap<>(); }
public void add(int number) { cnt.merge(number, 1, Integer::sum); }
public boolean find(int value) { for (Map.Entry<Integer, Integer> e : cnt.entrySet()) { int x = e.getKey(); int y = value - x; if (x == y) { if (e.getValue() >= 2) return true; } else if (cnt.containsKey(y)) { return true; } } return false; }}class TwoSum { cnt: Map<number, number>; constructor() { this.cnt = new Map(); } add(number: number): void { this.cnt.set(number, (this.cnt.get(number) || 0) + 1); } find(value: number): boolean { for (const [x, c] of this.cnt) { const y: number = value - x; if (x === y) { if (c >= 2) return true; } else if (this.cnt.has(y)) { return true; } } return false; }}Editorial#
Trading a sorted vector (faster find, slower add) for a hash map is the right call here because add calls dominate. The x == y guard catches the “use the same number twice” trap that’s easy to miss.
Complexity#
- Time:
O(1)add,O(n)find. - Space:
O(n).
Concept revision#
Related#