"This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/interactive-coding-challenges)."
]
},
{
"cell_type":"markdown",
"metadata":{},
"source":[
"# Solution Notebook"
]
},
{
"cell_type":"markdown",
"metadata":{},
"source":[
"## Problem: Implement a min heap with extract_min and insert methods.\n",
"\n",
"* [Constraints](#Constraints)\n",
"* [Test Cases](#Test-Cases)\n",
"* [Algorithm](#Algorithm)\n",
"* [Code](#Code)\n",
"* [Unit Test](#Unit-Test)"
]
},
{
"cell_type":"markdown",
"metadata":{},
"source":[
"## Constraints\n",
"\n",
"* Can we assume the inputs are ints?\n",
" * Yes\n",
"* Can we assume this fits memory?\n",
" * Yes"
]
},
{
"cell_type":"markdown",
"metadata":{},
"source":[
"## Test Cases\n",
"\n",
"* Extract min of an empty tree\n",
"* Extract min general case\n",
"* Insert into an empty tree\n",
"* Insert general case (left and right insert)\n",
"\n",
"<pre>\n",
" _5_\n",
" / \\\n",
" 20 15\n",
" / \\ / \\\n",
" 22 40 25\n",
"\n",
"extract_min(): 5\n",
"\n",
" _15_\n",
" / \\\n",
" 20 25\n",
" / \\ / \\\n",
" 22 40 \n",
"\n",
"insert(2):\n",
"\n",
" _2_\n",
" / \\\n",
" 20 5\n",
" / \\ / \\\n",
" 22 40 25 15\n",
"</pre>"
]
},
{
"cell_type":"markdown",
"metadata":{},
"source":[
"## Algorithm\n",
"\n",
"A heap is a complete binary tree where each node is smaller than its children.\n",
"\n",
"### extract_min\n",
"\n",
"<pre>\n",
" _5_\n",
" / \\\n",
" 20 15\n",
" / \\ / \\\n",
" 22 40 25\n",
"\n",
"Save the root as the value to be returned: 5\n",
"Move the right most element to the root: 25\n",
"\n",
" _25_\n",
" / \\\n",
" 20 15\n",
" / \\ / \\\n",
" 22 40 \n",
"\n",
"Bubble down 25: Swap 25 and 15 (the smaller child)\n",
"\n",
" _15_\n",
" / \\\n",
" 20 25\n",
" / \\ / \\\n",
" 22 40 \n",
"\n",
"Return 5\n",
"</pre>\n",
"\n",
"We'll use an array to represent the tree, here are the indices:\n",
"\n",
"<pre>\n",
" _0_\n",
" / \\\n",
" 1 2\n",
" / \\ / \\\n",
" 3 4 \n",
"</pre>\n",
"\n",
"To get to a child, we take 2 * index + 1 (left child) or 2 * index + 2 (right child).\n",
"\n",
"For example, the right child of index 1 is 2 * 1 + 2 = 4.\n",
"\n",
"Complexity:\n",
"* Time: O(lg(n))\n",
"* Space: O(lg(n)) for the recursion depth (tree height), or O(1) if using an iterative approach\n",
"\n",
"### insert\n",
"\n",
"<pre>\n",
" _5_\n",
" / \\\n",
" 20 15\n",
" / \\ / \\\n",
" 22 40 25\n",
"\n",
"insert(2):\n",
"Insert at the right-most spot to maintain the heap property.\n",
"\n",
" _5_\n",
" / \\\n",
" 20 15\n",
" / \\ / \\\n",
" 22 40 25 2\n",
"\n",
"Bubble up 2: Swap 2 and 15\n",
"\n",
" _5_\n",
" / \\\n",
" 20 2\n",
" / \\ / \\\n",
" 22 40 25 15\n",
"\n",
"Bubble up 2: Swap 2 and 5\n",
"\n",
" _2_\n",
" / \\\n",
" 20 5\n",
" / \\ / \\\n",
" 22 40 25 15\n",
"</pre>\n",
"\n",
"We'll use an array to represent the tree, here are the indices:\n",
"\n",
"<pre>\n",
" _0_\n",
" / \\\n",
" 1 2\n",
" / \\ / \\\n",
" 3 4 5 6\n",
"</pre>\n",
"\n",
"To get to a parent, we take (index - 1) // 2. \n",
"\n",
"For example, the parent of index 6 is (6 - 1) // 2 = 2.\n",
"\n",
"Complexity:\n",
"* Time: O(lg(n))\n",
"* Space: O(lg(n)) for the recursion depth (tree height), or O(1) if using an iterative approach"