{
  "id": "hashing/hash-map",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/hashing/hash-map",
  "topic": {
    "slug": "hashing",
    "title": "Hashing"
  },
  "title": "Hash Map",
  "tagline": "Turn a key straight into a location — the structure behind almost everything.",
  "vizKind": "hash",
  "complexity": {
    "time": {
      "best": "O(1)",
      "average": "O(1)",
      "worst": "O(n)"
    },
    "space": "O(n)",
    "growth": "constant",
    "note": "Insert and lookup are O(1) on average — one hash, one jump, a glance at a short chain. The worst case is O(n): if every key collides into one bucket, that bucket becomes a plain list you have to scan. A good hash function keeps that from happening."
  },
  "code": {
    "javascript": "const BUCKETS = 5;\n\nfunction insert(table, key) {\n  const i = key % BUCKETS;\n  table[i].push(key);\n}\n\nfunction has(table, key) {\n  const i = key % BUCKETS;\n  for (const k of table[i]) {\n    if (k === key) return true;\n  }\n  return false;\n}",
    "python": "BUCKETS = 5\n\ndef insert(table, key):\n    i = key % BUCKETS\n    table[i].append(key)\n\n\ndef has(table, key):\n    i = key % BUCKETS\n    for k in table[i]:\n        if k == key:\n            return True\n    return False\n",
    "java": "static final int BUCKETS = 5;\n\nvoid insert(List<List<Integer>> table, int key) {\n  int i = key % BUCKETS;\n  table.get(i).add(key);\n}\n\nboolean has(List<List<Integer>> table, int key) {\n  int i = key % BUCKETS;\n  for (int k : table.get(i)) {\n    if (k == key) return true;\n  }\n  return false;\n}",
    "cpp": "const int BUCKETS = 5;\n\nvoid insert(vector<vector<int>>& table, int key) {\n  int i = key % BUCKETS;\n  table[i].push_back(key);\n}\n\nbool has(vector<vector<int>>& table, int key) {\n  int i = key % BUCKETS;\n  for (int k : table[i]) {\n    if (k == key) return true;\n  }\n  return false;\n}"
  },
  "defaultInput": [
    17,
    22,
    3,
    8,
    12,
    27
  ],
  "defaultTarget": 12,
  "inputHint": "Keys get hashed into 5 buckets. Watch for collisions that share a bucket.",
  "pitfalls": [
    {
      "wrong": "Assuming lookups are always O(1).",
      "right": "Only on average. Pile every key into one bucket — a bad hash, or an attacker feeding you worst-case keys — and it degrades to scanning a list, O(n)."
    },
    {
      "wrong": "Expecting keys to come back in the order you inserted them.",
      "right": "A hash map scatters keys by their hash, not by insertion order. If you need order, that's a different tool (or a linked hash map)."
    },
    {
      "wrong": "Forgetting to handle collisions.",
      "right": "Two keys will eventually share a bucket. Without chaining (or another scheme), the second one overwrites the first and you silently lose data."
    }
  ],
  "quiz": [
    {
      "q": "How does a hash map find a key so fast?",
      "options": [
        "It searches every bucket quickly",
        "It calculates the key's bucket directly with a hash",
        "It keeps the keys sorted",
        "It remembers where everything is in a list"
      ],
      "answer": 1,
      "why": "The hash turns the key into a bucket index by arithmetic, so you jump straight there. No searching — that's what makes it O(1) on average."
    },
    {
      "q": "Two different keys hash to the same bucket. What is that called, and is it a problem?",
      "options": [
        "A crash — the map breaks",
        "A collision — expected, and handled by chaining",
        "A duplicate — one key is lost",
        "Impossible — hashes are unique"
      ],
      "answer": 1,
      "why": "It's a collision, and it's completely normal. Chaining stores both keys in the same bucket's list, so nothing is lost as long as chains stay short."
    },
    {
      "q": "When does a hash map's lookup degrade to O(n)?",
      "options": [
        "When it holds more than 100 items",
        "When many keys collide into the same bucket",
        "Never — it's always O(1)",
        "When the keys are large numbers"
      ],
      "answer": 1,
      "why": "If a bad hash sends everything to one bucket, that bucket is just a list you must scan end to end — O(n). Good hash functions spread keys evenly to prevent this."
    }
  ],
  "problems": [
    {
      "name": "Two Sum",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/two-sum/"
    },
    {
      "name": "Contains Duplicate",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/contains-duplicate/"
    },
    {
      "name": "Group Anagrams",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/group-anagrams/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 17,
    "frames": [
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 1,
        "variables": {},
        "explanation": "A hash map turns a key straight into a location. Instead of searching for where something is, it calculates where it must be — so lookups are almost instant, no matter how much you store.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        }
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 17,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "key": 17,
          "hash": "17 % 5 = 2"
        },
        "explanation": "Where does 17 go? Compute 17 % 5 = 2. So 17 belongs in bucket 2 — no searching, just arithmetic.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "key": 17,
          "bucket": 2,
          "collision": false
        },
        "explanation": "Bucket 2 was empty, so 17 drops straight in.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                }
              ]
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 22,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "key": 22,
          "hash": "22 % 5 = 2"
        },
        "explanation": "Where does 22 go? Compute 22 % 5 = 2. So 22 belongs in bucket 2 — no searching, just arithmetic.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "key": 22,
          "bucket": 2,
          "collision": true
        },
        "explanation": "Bucket 2 already has something — a collision. That's fine: just chain 22 onto the end of the bucket's list.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": []
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 3,
            "hash": 3
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "key": 3,
          "hash": "3 % 5 = 3"
        },
        "explanation": "Where does 3 go? Compute 3 % 5 = 3. So 3 belongs in bucket 3 — no searching, just arithmetic.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "key": 3,
          "bucket": 3,
          "collision": false
        },
        "explanation": "Bucket 3 was empty, so 3 drops straight in.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "found"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                }
              ]
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 8,
            "hash": 3
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "key": 8,
          "hash": "8 % 5 = 3"
        },
        "explanation": "Where does 8 go? Compute 8 % 5 = 3. So 8 belongs in bucket 3 — no searching, just arithmetic.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                }
              ]
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8,
                  "role": "found"
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "key": 8,
          "bucket": 3,
          "collision": true
        },
        "explanation": "Bucket 3 already has something — a collision. That's fine: just chain 8 onto the end of the bucket's list.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 12,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "key": 12,
          "hash": "12 % 5 = 2"
        },
        "explanation": "Where does 12 go? Compute 12 % 5 = 2. So 12 belongs in bucket 2 — no searching, just arithmetic.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                },
                {
                  "id": "e4-12",
                  "key": 12,
                  "role": "found"
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "key": 12,
          "bucket": 2,
          "collision": true
        },
        "explanation": "Bucket 2 already has something — a collision. That's fine: just chain 12 onto the end of the bucket's list.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                },
                {
                  "id": "e4-12",
                  "key": 12
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 27,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "key": 27,
          "hash": "27 % 5 = 2"
        },
        "explanation": "Where does 27 go? Compute 27 % 5 = 2. So 27 belongs in bucket 2 — no searching, just arithmetic.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                },
                {
                  "id": "e4-12",
                  "key": 12
                },
                {
                  "id": "e5-27",
                  "key": 27,
                  "role": "found"
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 5,
        "variables": {
          "key": 27,
          "bucket": 2,
          "collision": true
        },
        "explanation": "Bucket 2 already has something — a collision. That's fine: just chain 27 onto the end of the bucket's list.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "swap"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                },
                {
                  "id": "e4-12",
                  "key": 12
                },
                {
                  "id": "e5-27",
                  "key": 27
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ],
          "probe": {
            "key": 12,
            "hash": 2
          }
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 9,
        "variables": {
          "lookup": 12,
          "hash": "12 % 5 = 2"
        },
        "explanation": "Now look up 12. Same trick: 12 % 5 = 2, so if it's anywhere, it's in bucket 2. We ignore the other 4 buckets entirely.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17,
                  "role": "compare"
                },
                {
                  "id": "e1-22",
                  "key": 22
                },
                {
                  "id": "e4-12",
                  "key": 12
                },
                {
                  "id": "e5-27",
                  "key": 27
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 11,
        "variables": {
          "checking": 17,
          "target": 12
        },
        "explanation": "17 isn't 12. Check the next entry in this bucket's chain.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22,
                  "role": "compare"
                },
                {
                  "id": "e4-12",
                  "key": 12
                },
                {
                  "id": "e5-27",
                  "key": 27
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 11,
        "variables": {
          "checking": 22,
          "target": 12
        },
        "explanation": "22 isn't 12. Check the next entry in this bucket's chain.",
        "stats": {
          "comparisons": 2,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": {
          "buckets": [
            {
              "entries": []
            },
            {
              "entries": []
            },
            {
              "role": "active",
              "entries": [
                {
                  "id": "e0-17",
                  "key": 17
                },
                {
                  "id": "e1-22",
                  "key": 22
                },
                {
                  "id": "e4-12",
                  "key": 12,
                  "role": "found"
                },
                {
                  "id": "e5-27",
                  "key": 27
                }
              ]
            },
            {
              "entries": [
                {
                  "id": "e2-3",
                  "key": 3
                },
                {
                  "id": "e3-8",
                  "key": 8
                }
              ]
            },
            {
              "entries": []
            }
          ]
        },
        "pointers": [],
        "highlights": [],
        "codeLine": 11,
        "variables": {
          "checking": 12,
          "target": 12
        },
        "explanation": "12 is here. Found it after checking just 3 entries — only the ones that share its bucket.",
        "stats": {
          "comparisons": 3,
          "swaps": 0
        },
        "accent": "found"
      }
    ]
  }
}