From 7b573ceaa3cb5f2d1a632653f5c08464b891a488 Mon Sep 17 00:00:00 2001 From: Donne Martin Date: Sat, 25 Jun 2016 22:06:35 -0400 Subject: [PATCH] Polish bst successor challenge and solution (#82) Update constraints, test cases, tests, algorithm discussion, and code. --- .../bst_successor_challenge.ipynb | 21 +++++++++--- .../bst_successor_solution.ipynb | 34 +++++++++++++------ .../bst_successor/test_bst_successor.py | 6 ++++ 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/graphs_trees/bst_successor/bst_successor_challenge.ipynb b/graphs_trees/bst_successor/bst_successor_challenge.ipynb index 756019d..7f8eae4 100644 --- a/graphs_trees/bst_successor/bst_successor_challenge.ipynb +++ b/graphs_trees/bst_successor/bst_successor_challenge.ipynb @@ -36,7 +36,11 @@ "\n", "* If there is no successor, do we return None?\n", " * Yes\n", + "* If the input is None, should we throw an exception?\n", + " * Yes\n", "* Can we assume we already have a Node class that keeps track of parents?\n", + " * Yes\n", + "* Can we assume this fits memory?\n", " * Yes" ] }, @@ -57,10 +61,11 @@ " /\n", " 9\n", "\n", - "In: 4 Out: 5\n", - "In: 5 Out: 6\n", - "In: 8 Out: 9\n", - "In: 15 Out: None\n", + "In: None Out: Exception\n", + "In: 4 Out: 5\n", + "In: 5 Out: 6\n", + "In: 8 Out: 9\n", + "In: 15 Out: None\n", "" ] }, @@ -129,10 +134,15 @@ "source": [ "# %load test_bst_successor.py\n", "from nose.tools import assert_equal\n", + "from nose.tools import raises\n", "\n", "\n", "class TestBstSuccessor(object):\n", "\n", + " @raises(Exception)\n", + " def test_bst_successor_empty(self):\n", + " bst_successor(None)\n", + "\n", " def test_bst_successor(self):\n", " nodes = {}\n", " node = Node(5)\n", @@ -160,6 +170,7 @@ "def main():\n", " test = TestBstSuccessor()\n", " test.test_bst_successor()\n", + " test.test_bst_successor_empty()\n", "\n", "\n", "if __name__ == '__main__':\n", @@ -192,7 +203,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.3" + "version": "3.5.0" } }, "nbformat": 4, diff --git a/graphs_trees/bst_successor/bst_successor_solution.ipynb b/graphs_trees/bst_successor/bst_successor_solution.ipynb index 64de61a..e8ad1a4 100644 --- a/graphs_trees/bst_successor/bst_successor_solution.ipynb +++ b/graphs_trees/bst_successor/bst_successor_solution.ipynb @@ -35,7 +35,11 @@ "\n", "* If there is no successor, do we return None?\n", " * Yes\n", + "* If the input is None, should we throw an exception?\n", + " * Yes\n", "* Can we assume we already have a Node class that keeps track of parents?\n", + " * Yes\n", + "* Can we assume this fits memory?\n", " * Yes" ] }, @@ -56,10 +60,11 @@ " /\n", " 9\n", "\n", - "In: 4 Out: 5\n", - "In: 5 Out: 6\n", - "In: 8 Out: 9\n", - "In: 15 Out: None\n", + "In: None Out: Exception\n", + "In: 4 Out: 5\n", + "In: 5 Out: 6\n", + "In: 8 Out: 9\n", + "In: 15 Out: None\n", "" ] }, @@ -72,11 +77,12 @@ "* If the node has a right subtree, return the left-most node in the right subtree\n", "* Else, go up until you find a node that is its parent's left node\n", " * If you get to the root (ie node.parent is None), return None\n", + " * The original input node must be the largest in the tree\n", " * Else, return the parent\n", " \n", "Complexity:\n", - "* Time: O(n)\n", - "* Space: O(h), where h is the height of the tree" + "* Time: O(h), where h is the height of the tree\n", + "* Space: O(h), where h is the recursion depth (tree height), or O(1) if using an iterative approach" ] }, { @@ -107,7 +113,7 @@ "source": [ "def left_most_node(node):\n", " if node is None:\n", - " return\n", + " return None\n", " if node.left is None:\n", " return node.data\n", " return left_most_node(node.left)\n", @@ -115,7 +121,7 @@ "\n", "def bst_successor(node):\n", " if node is None:\n", - " return\n", + " raise Exception('Invalid input node')\n", " if node.right is not None:\n", " return left_most_node(node.right)\n", " else:\n", @@ -124,7 +130,9 @@ " node = node.parent\n", " parent = node.parent\n", " if parent is None:\n", - " return\n", + " # We reached the root, the original input node\n", + " # must be the largest element in the tree.\n", + " return None\n", " return parent.data" ] }, @@ -153,10 +161,15 @@ "source": [ "%%writefile test_bst_successor.py\n", "from nose.tools import assert_equal\n", + "from nose.tools import raises\n", "\n", "\n", "class TestBstSuccessor(object):\n", "\n", + " @raises(Exception)\n", + " def test_bst_successor_empty(self):\n", + " bst_successor(None)\n", + "\n", " def test_bst_successor(self):\n", " nodes = {}\n", " node = Node(5)\n", @@ -184,6 +197,7 @@ "def main():\n", " test = TestBstSuccessor()\n", " test.test_bst_successor()\n", + " test.test_bst_successor_empty()\n", "\n", "\n", "if __name__ == '__main__':\n", @@ -226,7 +240,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.4.3" + "version": "3.5.0" } }, "nbformat": 4, diff --git a/graphs_trees/bst_successor/test_bst_successor.py b/graphs_trees/bst_successor/test_bst_successor.py index 2e57be5..18a1e2c 100644 --- a/graphs_trees/bst_successor/test_bst_successor.py +++ b/graphs_trees/bst_successor/test_bst_successor.py @@ -1,8 +1,13 @@ from nose.tools import assert_equal +from nose.tools import raises class TestBstSuccessor(object): + @raises(Exception) + def test_bst_successor_empty(self): + bst_successor(None) + def test_bst_successor(self): nodes = {} node = Node(5) @@ -30,6 +35,7 @@ class TestBstSuccessor(object): def main(): test = TestBstSuccessor() test.test_bst_successor() + test.test_bst_successor_empty() if __name__ == '__main__':