From 7595e2a4996e3061ad1c1352ff4a3a16d949f8f8 Mon Sep 17 00:00:00 2001 From: Donne Martin Date: Fri, 3 Mar 2017 18:53:41 -0800 Subject: [PATCH] Add Hash Table solution --- .../hash_table/__init__.py | 0 .../hash_table/hash_map.ipynb | 121 ++++++++++++++++++ .../hash_table/hash_map.py | 38 ++++++ 3 files changed, 159 insertions(+) create mode 100644 solutions/object_oriented_design/hash_table/__init__.py create mode 100644 solutions/object_oriented_design/hash_table/hash_map.ipynb create mode 100644 solutions/object_oriented_design/hash_table/hash_map.py diff --git a/solutions/object_oriented_design/hash_table/__init__.py b/solutions/object_oriented_design/hash_table/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/solutions/object_oriented_design/hash_table/hash_map.ipynb b/solutions/object_oriented_design/hash_table/hash_map.ipynb new file mode 100644 index 0000000..b572889 --- /dev/null +++ b/solutions/object_oriented_design/hash_table/hash_map.ipynb @@ -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 +} diff --git a/solutions/object_oriented_design/hash_table/hash_map.py b/solutions/object_oriented_design/hash_table/hash_map.py new file mode 100644 index 0000000..beceb77 --- /dev/null +++ b/solutions/object_oriented_design/hash_table/hash_map.py @@ -0,0 +1,38 @@ +class Item(object): + + def __init__(self, key, value): + self.key = key + self.value = value + + +class HashTable(object): + + def __init__(self, size): + self.size = size + self.table = [[] for _ in range(self.size)] + + def _hash_function(self, key): + return key % self.size + + def set(self, key, value): + hash_index = self._hash_function(key) + for item in self.table[hash_index]: + if item.key == key: + item.value = value + return + self.table[hash_index].append(Item(key, value)) + + def get(self, key): + hash_index = self._hash_function(key) + for item in self.table[hash_index]: + if item.key == key: + return item.value + raise KeyError('Key not found') + + def remove(self, key): + hash_index = self._hash_function(key) + for index, item in enumerate(self.table[hash_index]): + if item.key == key: + del self.table[hash_index][index] + return + raise KeyError('Key not found') \ No newline at end of file