|
@@ -0,0 +1,121 @@
|
|
|
+{
|
|
|
+ "cells": [
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/system-design-primer-primer)."
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "# Design a hash map"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "## Constraints and assumptions\n",
|
|
|
+ "\n",
|
|
|
+ "* For simplicity, are the keys integers only?\n",
|
|
|
+ " * Yes\n",
|
|
|
+ "* For collision resolution, can we use chaining?\n",
|
|
|
+ " * Yes\n",
|
|
|
+ "* Do we have to worry about load factors?\n",
|
|
|
+ " * No\n",
|
|
|
+ "* Can we assume inputs are valid or do we have to validate them?\n",
|
|
|
+ " * Assume they're valid\n",
|
|
|
+ "* Can we assume this fits memory?\n",
|
|
|
+ " * Yes"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "markdown",
|
|
|
+ "metadata": {},
|
|
|
+ "source": [
|
|
|
+ "## Solution"
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "cell_type": "code",
|
|
|
+ "execution_count": 1,
|
|
|
+ "metadata": {
|
|
|
+ "collapsed": false
|
|
|
+ },
|
|
|
+ "outputs": [
|
|
|
+ {
|
|
|
+ "name": "stdout",
|
|
|
+ "output_type": "stream",
|
|
|
+ "text": [
|
|
|
+ "Overwriting hash_map.py\n"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "source": [
|
|
|
+ "%%writefile hash_map.py\n",
|
|
|
+ "class Item(object):\n",
|
|
|
+ "\n",
|
|
|
+ " def __init__(self, key, value):\n",
|
|
|
+ " self.key = key\n",
|
|
|
+ " self.value = value\n",
|
|
|
+ "\n",
|
|
|
+ "\n",
|
|
|
+ "class HashTable(object):\n",
|
|
|
+ "\n",
|
|
|
+ " def __init__(self, size):\n",
|
|
|
+ " self.size = size\n",
|
|
|
+ " self.table = [[] for _ in range(self.size)]\n",
|
|
|
+ "\n",
|
|
|
+ " def _hash_function(self, key):\n",
|
|
|
+ " return key % self.size\n",
|
|
|
+ "\n",
|
|
|
+ " def set(self, key, value):\n",
|
|
|
+ " hash_index = self._hash_function(key)\n",
|
|
|
+ " for item in self.table[hash_index]:\n",
|
|
|
+ " if item.key == key:\n",
|
|
|
+ " item.value = value\n",
|
|
|
+ " return\n",
|
|
|
+ " self.table[hash_index].append(Item(key, value))\n",
|
|
|
+ "\n",
|
|
|
+ " def get(self, key):\n",
|
|
|
+ " hash_index = self._hash_function(key)\n",
|
|
|
+ " for item in self.table[hash_index]:\n",
|
|
|
+ " if item.key == key:\n",
|
|
|
+ " return item.value\n",
|
|
|
+ " raise KeyError('Key not found')\n",
|
|
|
+ "\n",
|
|
|
+ " def remove(self, key):\n",
|
|
|
+ " hash_index = self._hash_function(key)\n",
|
|
|
+ " for index, item in enumerate(self.table[hash_index]):\n",
|
|
|
+ " if item.key == key:\n",
|
|
|
+ " del self.table[hash_index][index]\n",
|
|
|
+ " return\n",
|
|
|
+ " raise KeyError('Key not found')"
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ "metadata": {
|
|
|
+ "kernelspec": {
|
|
|
+ "display_name": "Python 3",
|
|
|
+ "language": "python",
|
|
|
+ "name": "python3"
|
|
|
+ },
|
|
|
+ "language_info": {
|
|
|
+ "codemirror_mode": {
|
|
|
+ "name": "ipython",
|
|
|
+ "version": 3
|
|
|
+ },
|
|
|
+ "file_extension": ".py",
|
|
|
+ "mimetype": "text/x-python",
|
|
|
+ "name": "python",
|
|
|
+ "nbconvert_exporter": "python",
|
|
|
+ "pygments_lexer": "ipython3",
|
|
|
+ "version": "3.4.3"
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "nbformat": 4,
|
|
|
+ "nbformat_minor": 0
|
|
|
+}
|