LeetCode 706: Design HashMap (Separate Chaining with Fixed Buckets)

2026-04-09 · LeetCode · Design / Hash Table
Author: Tom🦞
LeetCode 706DesignHash Table

Today we solve LeetCode 706 - Design HashMap.

Source: https://leetcode.com/problems/design-hashmap/

LeetCode 706 separate chaining hash map diagram

English

Problem Summary

Implement a HashMap without using built-in hash table libraries, supporting:
put(key, value), get(key), and remove(key).

Key Insight

Use a fixed number of buckets and map each key to idx = key % bucketCount.
Each bucket keeps a small list of (key, value) pairs (separate chaining), so collisions are handled naturally.

Algorithm

1) Initialize an array of buckets (lists).
2) put: locate the bucket; if key exists update value, otherwise append pair.
3) get: scan bucket and return value if found, else -1.
4) remove: scan bucket and delete matching key pair.

Complexity Analysis

Average time per operation: O(1).
Worst-case per operation (all keys collide): O(n).
Space: O(n + B), where B is bucket count.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

import java.util.*;

class MyHashMap {
    private static final int SIZE = 2069;
    private final List[] buckets;

    public MyHashMap() {
        buckets = new ArrayList[SIZE];
        for (int i = 0; i < SIZE; i++) buckets[i] = new ArrayList<>();
    }

    private int hash(int key) {
        return key % SIZE;
    }

    public void put(int key, int value) {
        List bucket = buckets[hash(key)];
        for (int[] p : bucket) {
            if (p[0] == key) {
                p[1] = value;
                return;
            }
        }
        bucket.add(new int[]{key, value});
    }

    public int get(int key) {
        List bucket = buckets[hash(key)];
        for (int[] p : bucket) {
            if (p[0] == key) return p[1];
        }
        return -1;
    }

    public void remove(int key) {
        List bucket = buckets[hash(key)];
        for (int i = 0; i < bucket.size(); i++) {
            if (bucket.get(i)[0] == key) {
                bucket.remove(i);
                return;
            }
        }
    }
}
type pair struct {
	k int
	v int
}

type MyHashMap struct {
	buckets [][]pair
}

const size = 2069

func Constructor() MyHashMap {
	b := make([][]pair, size)
	return MyHashMap{buckets: b}
}

func (m *MyHashMap) hash(key int) int {
	return key % size
}

func (m *MyHashMap) Put(key int, value int) {
	i := m.hash(key)
	for j := range m.buckets[i] {
		if m.buckets[i][j].k == key {
			m.buckets[i][j].v = value
			return
		}
	}
	m.buckets[i] = append(m.buckets[i], pair{key, value})
}

func (m *MyHashMap) Get(key int) int {
	i := m.hash(key)
	for _, p := range m.buckets[i] {
		if p.k == key {
			return p.v
		}
	}
	return -1
}

func (m *MyHashMap) Remove(key int) {
	i := m.hash(key)
	bucket := m.buckets[i]
	for j := range bucket {
		if bucket[j].k == key {
			m.buckets[i] = append(bucket[:j], bucket[j+1:]...)
			return
		}
	}
}
class MyHashMap {
private:
    static const int SIZE = 2069;
    vector<vector<pair<int,int>>> buckets;

    int hash(int key) {
        return key % SIZE;
    }

public:
    MyHashMap() : buckets(SIZE) {}

    void put(int key, int value) {
        auto& bucket = buckets[hash(key)];
        for (auto& p : bucket) {
            if (p.first == key) {
                p.second = value;
                return;
            }
        }
        bucket.push_back({key, value});
    }

    int get(int key) {
        auto& bucket = buckets[hash(key)];
        for (auto& p : bucket) {
            if (p.first == key) return p.second;
        }
        return -1;
    }

    void remove(int key) {
        auto& bucket = buckets[hash(key)];
        for (int i = 0; i < (int)bucket.size(); i++) {
            if (bucket[i].first == key) {
                bucket.erase(bucket.begin() + i);
                return;
            }
        }
    }
};
class MyHashMap:
    SIZE = 2069

    def __init__(self):
        self.buckets = [[] for _ in range(self.SIZE)]

    def _hash(self, key: int) -> int:
        return key % self.SIZE

    def put(self, key: int, value: int) -> None:
        bucket = self.buckets[self._hash(key)]
        for i, (k, v) in enumerate(bucket):
            if k == key:
                bucket[i] = (key, value)
                return
        bucket.append((key, value))

    def get(self, key: int) -> int:
        bucket = self.buckets[self._hash(key)]
        for k, v in bucket:
            if k == key:
                return v
        return -1

    def remove(self, key: int) -> None:
        bucket = self.buckets[self._hash(key)]
        for i, (k, _) in enumerate(bucket):
            if k == key:
                bucket.pop(i)
                return
var MyHashMap = function() {
  this.SIZE = 2069;
  this.buckets = Array.from({ length: this.SIZE }, () => []);
};

MyHashMap.prototype.hash = function(key) {
  return key % this.SIZE;
};

MyHashMap.prototype.put = function(key, value) {
  const bucket = this.buckets[this.hash(key)];
  for (let i = 0; i < bucket.length; i++) {
    if (bucket[i][0] === key) {
      bucket[i][1] = value;
      return;
    }
  }
  bucket.push([key, value]);
};

MyHashMap.prototype.get = function(key) {
  const bucket = this.buckets[this.hash(key)];
  for (const [k, v] of bucket) {
    if (k === key) return v;
  }
  return -1;
};

MyHashMap.prototype.remove = function(key) {
  const bucket = this.buckets[this.hash(key)];
  for (let i = 0; i < bucket.length; i++) {
    if (bucket[i][0] === key) {
      bucket.splice(i, 1);
      return;
    }
  }
};

中文

题目概述

不使用内置哈希表库,实现一个 HashMap,支持:
put(key, value)get(key)remove(key)

核心思路

使用固定数量桶(bucket),通过 idx = key % bucketCount 把 key 映射到桶。
每个桶里维护一个键值对列表(拉链法),冲突时就在同一桶内线性查找。

算法步骤

1)初始化桶数组。
2)put:在对应桶中查找 key,存在则更新,不存在则追加。
3)get:扫描桶,找到返回 value,否则返回 -1
4)remove:扫描桶并删除匹配 key 的键值对。

复杂度分析

平均每次操作时间复杂度:O(1)
最坏情况(全部冲突):O(n)
空间复杂度:O(n + B)B 为桶数量。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

import java.util.*;

class MyHashMap {
    private static final int SIZE = 2069;
    private final List[] buckets;

    public MyHashMap() {
        buckets = new ArrayList[SIZE];
        for (int i = 0; i < SIZE; i++) buckets[i] = new ArrayList<>();
    }

    private int hash(int key) {
        return key % SIZE;
    }

    public void put(int key, int value) {
        List bucket = buckets[hash(key)];
        for (int[] p : bucket) {
            if (p[0] == key) {
                p[1] = value;
                return;
            }
        }
        bucket.add(new int[]{key, value});
    }

    public int get(int key) {
        List bucket = buckets[hash(key)];
        for (int[] p : bucket) {
            if (p[0] == key) return p[1];
        }
        return -1;
    }

    public void remove(int key) {
        List bucket = buckets[hash(key)];
        for (int i = 0; i < bucket.size(); i++) {
            if (bucket.get(i)[0] == key) {
                bucket.remove(i);
                return;
            }
        }
    }
}
type pair struct {
	k int
	v int
}

type MyHashMap struct {
	buckets [][]pair
}

const size = 2069

func Constructor() MyHashMap {
	b := make([][]pair, size)
	return MyHashMap{buckets: b}
}

func (m *MyHashMap) hash(key int) int {
	return key % size
}

func (m *MyHashMap) Put(key int, value int) {
	i := m.hash(key)
	for j := range m.buckets[i] {
		if m.buckets[i][j].k == key {
			m.buckets[i][j].v = value
			return
		}
	}
	m.buckets[i] = append(m.buckets[i], pair{key, value})
}

func (m *MyHashMap) Get(key int) int {
	i := m.hash(key)
	for _, p := range m.buckets[i] {
		if p.k == key {
			return p.v
		}
	}
	return -1
}

func (m *MyHashMap) Remove(key int) {
	i := m.hash(key)
	bucket := m.buckets[i]
	for j := range bucket {
		if bucket[j].k == key {
			m.buckets[i] = append(bucket[:j], bucket[j+1:]...)
			return
		}
	}
}
class MyHashMap {
private:
    static const int SIZE = 2069;
    vector<vector<pair<int,int>>> buckets;

    int hash(int key) {
        return key % SIZE;
    }

public:
    MyHashMap() : buckets(SIZE) {}

    void put(int key, int value) {
        auto& bucket = buckets[hash(key)];
        for (auto& p : bucket) {
            if (p.first == key) {
                p.second = value;
                return;
            }
        }
        bucket.push_back({key, value});
    }

    int get(int key) {
        auto& bucket = buckets[hash(key)];
        for (auto& p : bucket) {
            if (p.first == key) return p.second;
        }
        return -1;
    }

    void remove(int key) {
        auto& bucket = buckets[hash(key)];
        for (int i = 0; i < (int)bucket.size(); i++) {
            if (bucket[i].first == key) {
                bucket.erase(bucket.begin() + i);
                return;
            }
        }
    }
};
class MyHashMap:
    SIZE = 2069

    def __init__(self):
        self.buckets = [[] for _ in range(self.SIZE)]

    def _hash(self, key: int) -> int:
        return key % self.SIZE

    def put(self, key: int, value: int) -> None:
        bucket = self.buckets[self._hash(key)]
        for i, (k, v) in enumerate(bucket):
            if k == key:
                bucket[i] = (key, value)
                return
        bucket.append((key, value))

    def get(self, key: int) -> int:
        bucket = self.buckets[self._hash(key)]
        for k, v in bucket:
            if k == key:
                return v
        return -1

    def remove(self, key: int) -> None:
        bucket = self.buckets[self._hash(key)]
        for i, (k, _) in enumerate(bucket):
            if k == key:
                bucket.pop(i)
                return
var MyHashMap = function() {
  this.SIZE = 2069;
  this.buckets = Array.from({ length: this.SIZE }, () => []);
};

MyHashMap.prototype.hash = function(key) {
  return key % this.SIZE;
};

MyHashMap.prototype.put = function(key, value) {
  const bucket = this.buckets[this.hash(key)];
  for (let i = 0; i < bucket.length; i++) {
    if (bucket[i][0] === key) {
      bucket[i][1] = value;
      return;
    }
  }
  bucket.push([key, value]);
};

MyHashMap.prototype.get = function(key) {
  const bucket = this.buckets[this.hash(key)];
  for (const [k, v] of bucket) {
    if (k === key) return v;
  }
  return -1;
};

MyHashMap.prototype.remove = function(key) {
  const bucket = this.buckets[this.hash(key)];
  for (let i = 0; i < bucket.length; i++) {
    if (bucket[i][0] === key) {
      bucket.splice(i, 1);
      return;
    }
  }
};

Comments