{ "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/interactive-coding-challenges)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Solution Notebook" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Problem: Create a binary search tree with minimal height from a sorted array.\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", "* Is the array in increasing order?\n", " * Yes\n", "* Are the array elements unique?\n", " * Yes\n", "* Can we assume we already have a Node class with an insert method?\n", " * Yes\n", "* Can we assume this fits memory?\n", " * Yes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Test Cases\n", "\n", "* 0, 1, 2, 3, 4, 5, 6 -> height 3\n", "* 0, 1, 2, 3, 4, 5, 6, 7 -> height 4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Algorithm\n", "\n", "To create a bst with minimum height, we need to use the middle element as the root. We'll use recursion to divide the array in half and continue to pick the middle element from the left and right halves as the nodes to insert in the tree.\n", "\n", "* create_min_bst(array, start, end)\n", "* Base case: Stop when end < start\n", "* Create a node with the mid element\n", "* Recursively build node.left by calling create_min_bst using the left sub array\n", "* Recursively build node.right by calling create_min_bst using the right sub array\n", "* Return the node\n", " \n", "Complexity:\n", "* Time: O(n)\n", "* Space: O(h), where h is the tree's height (since this is a tree with minimum height, h = log n)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "%run ../bst/bst.py" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from __future__ import division\n", "\n", "\n", "class MinBst(object):\n", "\n", " def create_min_bst(self, array):\n", " if array is None:\n", " return\n", " return self._create_min_bst(array, 0, len(array) - 1)\n", "\n", " def _create_min_bst(self, array, start, end):\n", " if end < start:\n", " return None\n", " mid = (start + end) // 2\n", " node = Node(array[mid])\n", " node.left = self._create_min_bst(array, start, mid - 1)\n", " node.right = self._create_min_bst(array, mid + 1, end)\n", " return node" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Unit Test" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting test_bst_min.py\n" ] } ], "source": [ "%%writefile test_bst_min.py\n", "import unittest\n", "\n", "\n", "def height(node):\n", " if node is None:\n", " return 0\n", " return 1 + max(height(node.left),\n", " height(node.right))\n", "\n", "\n", "class TestBstMin(unittest.TestCase):\n", "\n", " def test_bst_min(self):\n", " min_bst = MinBst()\n", " array = [0, 1, 2, 3, 4, 5, 6]\n", " root = min_bst.create_min_bst(array)\n", " self.assertEqual(height(root), 3)\n", "\n", " min_bst = MinBst()\n", " array = [0, 1, 2, 3, 4, 5, 6, 7]\n", " root = min_bst.create_min_bst(array)\n", " self.assertEqual(height(root), 4)\n", "\n", " print('Success: test_bst_min')\n", "\n", "\n", "def main():\n", " test = TestBstMin()\n", " test.test_bst_min()\n", "\n", "\n", "if __name__ == '__main__':\n", " main()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Success: test_bst_min\n" ] } ], "source": [ "%run -i test_bst_min.py" ] } ], "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.7.2" } }, "nbformat": 4, "nbformat_minor": 1 }