diff --git a/graphs_trees/invert_tree/__init__.py b/graphs_trees/invert_tree/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/graphs_trees/invert_tree/invert_tree_challenge.ipynb b/graphs_trees/invert_tree/invert_tree_challenge.ipynb new file mode 100644 index 0000000..d701ae8 --- /dev/null +++ b/graphs_trees/invert_tree/invert_tree_challenge.ipynb @@ -0,0 +1,200 @@ +{ + "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: Invert a binary tree.\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", + "* What does it mean to invert a binary tree?\n", + " * Swap all left and right node pairs\n", + "* Can we assume we already have a Node class?\n", + " * Yes\n", + "* Can we assume the inputs are valid?\n", + " * No\n", + "* Can we assume this fits memory?\n", + " * Yes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test Cases\n", + "\n", + "
\n", + "Input:\n", + " 5\n", + " / \\\n", + " 2 7\n", + " / \\ / \\\n", + "1 3 6 9\n", + "\n", + "Output:\n", + " 5\n", + " / \\\n", + " 7 2\n", + " / \\ / \\\n", + "9 6 3 1\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Algorithm\n", + "\n", + "Refer to the [Solution Notebook](). 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class InverseBst(Bst):\n", + "\n", + " def invert_tree(self):\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": false + }, + "outputs": [], + "source": [ + "# %load test_invert_tree.py\n", + "from nose.tools import assert_equal\n", + "\n", + "\n", + "class TestInvertTree(object):\n", + "\n", + " def test_invert_tree(self):\n", + " root = Node(5)\n", + " bst = InverseBst(root)\n", + " node2 = bst.insert(2)\n", + " node3 = bst.insert(3)\n", + " node1 = bst.insert(1)\n", + " node7 = bst.insert(7)\n", + " node6 = bst.insert(6)\n", + " node9 = bst.insert(9)\n", + " result = bst.invert_tree()\n", + " assert_equal(result, root)\n", + " assert_equal(result.left, node7)\n", + " assert_equal(result.right, node2)\n", + " assert_equal(result.left.left, node9)\n", + " assert_equal(result.left.right, node6)\n", + " assert_equal(result.right.left, node3)\n", + " assert_equal(result.right.right, node1)\n", + " print('Success: test_invert_tree')\n", + "\n", + "\n", + "def main():\n", + " test = TestInvertTree()\n", + " test.test_invert_tree()\n", + "\n", + "\n", + "if __name__ == '__main__':\n", + " main()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solution Notebook\n", + "\n", + "Review the [Solution Notebook]() for a discussion on algorithms and code solutions." + ] + } + ], + "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.5.0" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/graphs_trees/invert_tree/invert_tree_solution.ipynb b/graphs_trees/invert_tree/invert_tree_solution.ipynb new file mode 100644 index 0000000..3037e57 --- /dev/null +++ b/graphs_trees/invert_tree/invert_tree_solution.ipynb @@ -0,0 +1,229 @@ +{ + "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: Invert a binary tree.\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", + "* What does it mean to invert a binary tree?\n", + " * Swap all left and right node pairs\n", + "* Can we assume we already have a Node class?\n", + " * Yes\n", + "* Can we assume the inputs are valid?\n", + " * No\n", + "* Can we assume this fits memory?\n", + " * Yes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test Cases\n", + "\n", + "
\n", + "Input:\n", + " 5\n", + " / \\\n", + " 2 7\n", + " / \\ / \\\n", + "1 3 6 9\n", + "\n", + "Output:\n", + " 5\n", + " / \\\n", + " 7 2\n", + " / \\ / \\\n", + "9 6 3 1\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Algorithm\n", + "\n", + "* Base case\n", + " * If the root is None, return\n", + "* Recursive case\n", + " * Recurse on the left node\n", + " * Recurse on the right node\n", + " * Swap left and right\n", + "* Return the node\n", + "\n", + "Complexity:\n", + "* Time: O(n)\n", + "* Space: O(h), where h is the height, for the recursion depth" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%run ../bst/bst.py" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class InverseBst(Bst):\n", + "\n", + " def invert_tree(self):\n", + " if self.root is None:\n", + " raise TypeError('root cannot be None')\n", + " return self._invert_tree(self.root)\n", + "\n", + " def _invert_tree(self, root):\n", + " if root is None:\n", + " return\n", + " self._invert_tree(root.left)\n", + " self._invert_tree(root.right)\n", + " root.left, root.right = root.right, root.left\n", + " return root" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unit Test" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting test_invert_tree.py\n" + ] + } + ], + "source": [ + "%%writefile test_invert_tree.py\n", + "from nose.tools import assert_equal, assert_raises\n", + "\n", + "\n", + "class TestInvertTree(object):\n", + "\n", + " def test_invert_tree(self):\n", + " root = Node(5)\n", + " bst = InverseBst(root)\n", + " node2 = bst.insert(2)\n", + " node3 = bst.insert(3)\n", + " node1 = bst.insert(1)\n", + " node7 = bst.insert(7)\n", + " node6 = bst.insert(6)\n", + " node9 = bst.insert(9)\n", + " result = bst.invert_tree()\n", + " assert_equal(result, root)\n", + " assert_equal(result.left, node7)\n", + " assert_equal(result.right, node2)\n", + " assert_equal(result.left.left, node9)\n", + " assert_equal(result.left.right, node6)\n", + " assert_equal(result.right.left, node3)\n", + " assert_equal(result.right.right, node1)\n", + " print('Success: test_invert_tree')\n", + "\n", + "\n", + "def main():\n", + " test = TestInvertTree()\n", + " test.test_invert_tree()\n", + "\n", + "\n", + "if __name__ == '__main__':\n", + " main()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: test_invert_tree\n" + ] + } + ], + "source": [ + "%run -i test_invert_tree.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.5.0" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/graphs_trees/invert_tree/test_invert_tree.py b/graphs_trees/invert_tree/test_invert_tree.py new file mode 100644 index 0000000..ab33458 --- /dev/null +++ b/graphs_trees/invert_tree/test_invert_tree.py @@ -0,0 +1,32 @@ +from nose.tools import assert_equal, assert_raises + + +class TestInvertTree(object): + + def test_invert_tree(self): + root = Node(5) + bst = InverseBst(root) + node2 = bst.insert(2) + node3 = bst.insert(3) + node1 = bst.insert(1) + node7 = bst.insert(7) + node6 = bst.insert(6) + node9 = bst.insert(9) + result = bst.invert_tree() + assert_equal(result, root) + assert_equal(result.left, node7) + assert_equal(result.right, node2) + assert_equal(result.left.left, node9) + assert_equal(result.left.right, node6) + assert_equal(result.right.left, node3) + assert_equal(result.right.right, node1) + print('Success: test_invert_tree') + + +def main(): + test = TestInvertTree() + test.test_invert_tree() + + +if __name__ == '__main__': + main() \ No newline at end of file