# Optimal Hash Table Implementations for Competitive Programming: A Cross-Language Guide from leetcode-master

> Discover optimal hash table implementations in C++, Java, and Python for competitive programming. Achieve O(1) average time complexity for common operations with built-in unordered maps.

- Repository: [程序员Carl/leetcode-master](https://github.com/youngyangyang04/leetcode-master)
- Tags: deep-dive
- Published: 2026-03-05

---

**The leetcode-master repository recommends using each language's built-in unordered hash map—such as `std::unordered_map` in C++, `HashMap` in Java, and `dict` in Python—to achieve O(1) average time complexity for lookups, insertions, and deletions in algorithm problems.**

The `youngyangyang04/leetcode-master` repository is a comprehensive resource for algorithm interview preparation, providing solutions in over a dozen programming languages. When solving problems that require fast membership testing or frequency counting, selecting the **optimal hash table implementation** for your specific language is critical for meeting strict time complexity constraints on LeetCode.

## Why Hash Tables Are Essential for Algorithm Problems

Hash tables provide **O(1) average time complexity** for insertions, deletions, and lookups, making them indispensable for problems involving two-sum pairs, anagram detection, and frequency analysis. According to the repository's hash table theory documentation in `problems/哈希表理论基础.md`, when you need to quickly determine if an element exists in a set, you should immediately consider hash-based solutions.

The author emphasizes that unordered containers offer superior performance to ordered alternatives: *"当我们需要快速判断一个元素是否出现集合里，就要第一时间想到哈希法… 选择 `std::unordered_map` 效率更高！"* (When we need to quickly determine whether an element appears in a collection, we should immediately think of the hash method... choosing `std::unordered_map` is more efficient!).

## Optimal Hash Table Implementations by Language

The repository's canonical example in `problems/0001.两数之和.md` demonstrates the preferred hash table implementation for each supported language. Below are the specific recommendations with code excerpts extracted directly from the source files.

### C++ – std::unordered_map

For C++, the repository explicitly recommends `std::unordered_map` over `std::map` because the former implements a hash table with O(1) average operations, while the latter uses a red-black tree with O(log n) complexity. The implementation in `problems/0001.两数之和.md` (lines 95-104) uses this container for the two-sum solution.

```cpp
std::unordered_map<int,int> m;
for (int i = 0; i < nums.size(); ++i) {
    auto it = m.find(target - nums[i]);
    if (it != m.end()) return {it->second, i};
    m.emplace(nums[i], i);
}

```

### Java – java.util.HashMap

Java solutions utilize `java.util.HashMap` as the default unordered map implementation. The code in `problems/0001.两数之和.md` (lines 40-49) demonstrates constant-time operations for membership testing.

```java
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
    int need = target - nums[i];
    if (map.containsKey(need)) return new int[]{map.get(need), i};
    map.put(nums[i], i);
}

```

### Go – Built-in map

Go's native `map` type is a hash table with O(1) average performance. The repository uses it directly in `problems/0001.两数之和.md` (lines 88-96) without requiring external imports.

```go
m := make(map[int]int)
for i, v := range nums {
    if j, ok := m[target-v]; ok {
        return []int{j, i}
    }
    m[v] = i
}

```

### Python – dict

Python's `dict` is a highly optimized hash table. As shown in `problems/0001.两数之和.md` (lines 13-21), it provides the most concise syntax for the two-sum solution.

```python
seen = {}
for i, v in enumerate(nums):
    if target - v in seen:
        return [seen[target - v], i]
    seen[v] = i

```

### Rust – std::collections::HashMap

Rust's standard library provides `HashMap` with fast lookups. The implementation in `problems/0001.两数之和.md` (lines 4-7) pre-allocates capacity for efficiency.

```rust
use std::collections::HashMap;
let mut map = HashMap::with_capacity(nums.len());
for (i, &v) in nums.iter().enumerate() {
    if let Some(&j) = map.get(&(target - v)) {
        return vec![j as i32, i as i32];
    }
    map.insert(v, i);
}

```

### JavaScript – Plain Object {}

JavaScript solutions use a plain object `{}` as a hash map because property access is O(1) and requires no imports. The code in `problems/0001.两数之和.md` (lines 44-50) demonstrates this pattern.

```javascript
const hash = {};
for (let i = 0; i < nums.length; i++) {
    const need = target - nums[i];
    if (hash[need] !== undefined) return [hash[need], i];
    hash[nums[i]] = i;
}

```

### TypeScript – Map<number, number>

TypeScript implementations utilize the ES6 `Map` object for explicit key-value semantics and type safety, as shown in `problems/0001.两数之和.md` (lines 58-70).

```typescript
const mp = new Map<number, number>();
for (let i = 0; i < nums.length; i++) {
    const idx = mp.get(target - nums[i]);
    if (idx !== undefined) return [idx, i];
    mp.set(nums[i], i);
}

```

### PHP – Associative Array []

PHP's associative arrays are hash tables under the hood. The solution in `problems/0001.两数之和.md` (lines 77-88) uses this native structure.

```php
$map = [];
foreach ($nums as $i => $num) {
    $need = $target - $num;
    if (isset($map[$need])) return [$i, $map[$need]];
    $map[$num] = $i;
}

```

### Swift – Dictionary<Int, Int>

Swift's `Dictionary` provides O(1) average lookups. The implementation in `problems/0001.两数之和.md` (lines 96-104) uses this type.

```swift
var dict = [Int:Int]()
for (i, v) in nums.enumerated() {
    if let j = dict[target - v] { return [j, i] }
    dict[v] = i
}

```

### Scala – mutable.HashMap

Scala solutions use `scala.collection.mutable.HashMap` for constant-time mutable operations, as demonstrated in `problems/0001.两数之和.md` (lines 14-22).

```scala
val hm = scala.collection.mutable.HashMap[Int,Int]()
for (i <- nums.indices) {
  val need = target - nums(i)
  if (hm.contains(need)) return Array(hm(need), i)
  hm(nums(i)) = i
}

```

### C# – Dictionary<int,int>

The .NET `Dictionary` implements a hash table with O(1) average performance. The code in `problems/0001.两数之和.md` (lines 38-46) demonstrates its usage.

```csharp
var dict = new Dictionary<int,int>();
for (int i = 0; i < nums.Length; i++) {
    int need = target - nums[i];
    if (dict.TryGetValue(need, out int j)) return new []{j, i};
    dict[nums[i]] = i;
}

```

### Dart – HashMap<int,int>

Dart's `HashMap` from `dart:collection` provides true hash-table semantics. The solution in `problems/0001.两数之和.md` (lines 56-64) uses this implementation.

```dart
final map = HashMap<int,int>();
for (int i = 0; i < nums.length; i++) {
  final need = target - nums[i];
  if (map.containsKey(need)) return [map[need]!, i];
  map[nums[i]] = i;
}

```

### C – uthash Library

For C, which lacks a built-in hash table, the repository utilizes the **uthash** macro library. This portable implementation uses `UT_hash_handle` to manage hash buckets. The code in `problems/0001.两数之和.md` (lines 84-101) demonstrates this pattern.

```c
typedef struct { int key, value; UT_hash_handle hh; } map;
map *hash = NULL;
for (int i = 0; i < n; ++i) {
    map *e; HASH_FIND_INT(hash, &nums[i], e);
    if (!e) { e = malloc(sizeof *e); e->key = nums[i]; e->value = i; HASH_ADD_INT(hash, key, e); }
}
for (int i = 0; i < n; ++i) {
    map *found; int need = target - nums[i];
    HASH_FIND_INT(hash, &need, found);
    if (found && found->value != i) return (int[]){i, found->value};
}

```

## When to Use Arrays Instead of Hash Maps

While hash tables are the default choice for arbitrary keys, the repository demonstrates that **arrays can serve as hash tables** when the key domain is small and fixed. In `problems/0242.有效的字母异位词.md`, the solution uses a fixed-size array of 26 integers to count character frequencies rather than a hash map.

This approach eliminates hash function computation overhead and improves cache locality, but it only works when keys are constrained to a specific range (such as ASCII characters or small integers).

## Summary

- **Optimal hash table implementations** vary by language but consistently provide O(1) average time complexity for lookups, insertions, and deletions.
- The `leetcode-master` repository demonstrates that you should always prefer **unordered containers** (like `std::unordered_map`, `HashMap`, or `dict`) over ordered tree-based structures unless sorting is required.
- For languages without native hash tables (such as C), the **uthash** library provides a robust, portable solution.
- When the key domain is restricted to a small fixed range (e.g., 26 letters), **arrays** can replace hash maps for better performance.

## Frequently Asked Questions

### Why does the repository recommend unordered_map over map in C++?

The repository explicitly recommends `std::unordered_map` over `std::map` because the former implements a hash table with O(1) average operations, while the latter uses a red-black tree with O(log n) complexity. For LeetCode problems that only require existence checks or frequency counting without sorted traversal, the hash table implementation provides superior performance and is the optimal choice.

### Can I use a plain array instead of a hash map in every language?

No, arrays are only suitable when the key domain is small and fixed, such as counting occurrences of lowercase English letters (26 characters) or digits (0-9). The repository demonstrates this pattern in `problems/0242.有效的字母异位词.md` for anagram problems. For arbitrary integer ranges or string keys, a proper hash table implementation is required to avoid excessive memory usage and collision handling issues.

### What is the time complexity guarantee for these hash table implementations?

All implementations presented in the repository provide **O(1) average time complexity** for insertions, deletions, and lookups under normal conditions. However, in worst-case scenarios where all keys collide, complexity degrades to O(n). The repository notes that LeetCode's test data is typically designed to avoid such pathological cases, making these hash tables reliable for competitive programming constraints.

### How does the C implementation using uthash compare to native implementations?

The **uthash** library used in the C implementation provides macro-based hash table functionality that is portable and efficient, though it requires manual memory management. Unlike native implementations in higher-level languages, uthash does not provide automatic resizing or garbage collection, but it still achieves O(1) average operations. The repository includes this in `problems/0001.两数之和.md` to demonstrate that C developers can achieve comparable performance to modern languages using well-tested third-party libraries.