diff --git a/README.md b/README.md index 70e8412..6b6fb24 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,7 @@ Challenges, solutions, and unit tests are presented in the form of **IPython/Jup | Implement depth-first search (pre-, in-, post-order) on a tree | [Challenge](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/tree_dfs/dfs_challenge.ipynb)│[Solution](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/tree_dfs/dfs_solution.ipynb) | | Implement breadth-first search on a tree | [Challenge](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/tree_bfs/bfs_challenge.ipynb)│[Solution](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/tree_bfs/bfs_solution.ipynb) | | Determine the height of a tree | [Challenge](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/tree_height/height_challenge.ipynb)│[Solution](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/tree_height/height_solution.ipynb) | +| Create a binary search tree with minimal height from a sorted array | [Challenge](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/bst_min/bst_min_challenge.ipynb)│[Solution](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/bst_min/bst_min_solution.ipynb) | | Implement a binary search tree | [Challenge](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/bst/bst_challenge.ipynb)│[Solution](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/bst/bst_solution.ipynb) | | Implement depth-first search on a graph | [Challenge](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/graph_dfs/dfs_challenge.ipynb)│[Solution](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/graph_dfs/dfs_solution.ipynb) | | Implement breadth-first search on a graph | [Challenge](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/graph_bfs/bfs_challenge.ipynb)│[Solution](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/graph_bfs/bfs_solution.ipynb) | diff --git a/graphs_trees/bst_min/__init__.py b/graphs_trees/bst_min/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/graphs_trees/bst_min/bst_min_challenge.ipynb b/graphs_trees/bst_min/bst_min_challenge.ipynb new file mode 100644 index 0000000..9ec1945 --- /dev/null +++ b/graphs_trees/bst_min/bst_min_challenge.ipynb @@ -0,0 +1,193 @@ +{ + "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": [ + "# Challenge 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)\n", + "* [Solution Notebook](#Solution-Notebook)" + ] + }, + { + "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" + ] + }, + { + "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", + "Refer to the [Solution Notebook](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/bst_min/bst_min_solution.ipynb). If you are stuck and need a hint, the solution notebook's algorithm discussion might be a good place to start." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%run ../bst/bst.py\n", + "%load ../bst/bst.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def create_min_bst(array):\n", + " # TODO: Implement me\n", + " # Calls __create_min_bst__\n", + " pass \n", + "\n", + "\n", + "def __create_min_bst__(array, start, end):\n", + " # TODO: Implement me\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unit Test" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**The following unit test is expected to fail until you solve the challenge.**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%run ../tree_height/height.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# %load test_bst_min.py\n", + "from nose.tools import assert_equal\n", + "\n", + "\n", + "class TestBstMin(object):\n", + "\n", + " def test_bst_min(self):\n", + " array = [0, 1, 2, 3, 4, 5, 6]\n", + " root = create_min_bst(array)\n", + " assert_equal(height(root), 3)\n", + "\n", + " array = [0, 1, 2, 3, 4, 5, 6, 7]\n", + " root = create_min_bst(array)\n", + " assert_equal(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": "markdown", + "metadata": {}, + "source": [ + "## Solution Notebook\n", + "\n", + "Review the [Solution Notebook](http://nbviewer.ipython.org/github/donnemartin/interactive-coding-challenges/blob/master/graphs_trees/bst_min/bst_min_solution.ipynb) for a discussion on algorithms and code solutions." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/graphs_trees/bst_min/bst_min_solution.ipynb b/graphs_trees/bst_min/bst_min_solution.ipynb new file mode 100644 index 0000000..2f6fe9a --- /dev/null +++ b/graphs_trees/bst_min/bst_min_solution.ipynb @@ -0,0 +1,221 @@ +{ + "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" + ] + }, + { + "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(1)\n", + "* Space: O(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%run ../bst/bst.py" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from __future__ import division\n", + "\n", + "\n", + "def create_min_bst(array):\n", + " if array is None:\n", + " return\n", + " return __create_min_bst__(array, 0, len(array) - 1)\n", + "\n", + "\n", + "def __create_min_bst__(array, start, end):\n", + " if end < start:\n", + " return\n", + " mid = (start + end) // 2\n", + " node = Node(array[mid])\n", + " node.left = __create_min_bst__(array, start, mid-1)\n", + " node.right = __create_min_bst__(array, mid+1, end)\n", + " return node" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unit Test" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%run ../tree_height/height.py" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting test_bst_min.py\n" + ] + } + ], + "source": [ + "%%writefile test_bst_min.py\n", + "from nose.tools import assert_equal\n", + "\n", + "\n", + "class TestBstMin(object):\n", + "\n", + " def test_bst_min(self):\n", + " array = [0, 1, 2, 3, 4, 5, 6]\n", + " root = create_min_bst(array)\n", + " assert_equal(height(root), 3)\n", + "\n", + " array = [0, 1, 2, 3, 4, 5, 6, 7]\n", + " root = create_min_bst(array)\n", + " assert_equal(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": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: test_bst_min\n" + ] + } + ], + "source": [ + "%run -i test_bst_min.py" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/graphs_trees/bst_min/test_bst_min.py b/graphs_trees/bst_min/test_bst_min.py new file mode 100644 index 0000000..eb1e510 --- /dev/null +++ b/graphs_trees/bst_min/test_bst_min.py @@ -0,0 +1,24 @@ +from nose.tools import assert_equal + + +class TestBstMin(object): + + def test_bst_min(self): + array = [0, 1, 2, 3, 4, 5, 6] + root = create_min_bst(array) + assert_equal(height(root), 3) + + array = [0, 1, 2, 3, 4, 5, 6, 7] + root = create_min_bst(array) + assert_equal(height(root), 4) + + print('Success: test_bst_min') + + +def main(): + test = TestBstMin() + test.test_bst_min() + + +if __name__ == '__main__': + main() \ No newline at end of file