diff --git a/arrays-strings/reverse_string.ipynb b/arrays-strings/reverse_string.ipynb index 291e0ba..927b49e 100644 --- a/arrays-strings/reverse_string.ipynb +++ b/arrays-strings/reverse_string.ipynb @@ -11,13 +11,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Problem: Implement the function void Reverse(char* str)\n", + "## Problem: Implement a function to reverse a string.\n", "\n", "* [Clarifying Questions](#Clarifying-Questions)\n", "* [Test Cases](#Test-Cases)\n", "* [Algorithm](#Algorithm)\n", "* [Code](#Code)\n", - "* [Pythonic-Code: Not In-Place](#Pythonic-Code:-Not-In-Place)" + "* [C Algorithm](C-Algorithm)\n", + "* [C Code]()\n", + "* [Pythonic-Code](#Pythonic-Code)" ] }, { @@ -26,10 +28,10 @@ "source": [ "## Clarifying Questions\n", "\n", - "* Based on the function signature, it seems you have to implement this in C/C++?\n", - " * Yes\n", - "* Can you use additional data structures?\n", - " * No, do the operation in-place" + "* Can I use the slice operator or the reversed function?\n", + " * No\n", + "* Since Python string are immutable, can I use a list instead?\n", + " * Yes" ] }, { @@ -43,12 +45,80 @@ "* 'foo bar' -> 'rab oof'" ] }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from nose.tools import assert_equal\n", + "\n", + "class Test(object):\n", + " def test_reversed(self, func):\n", + " assert_equal(func(None), None)\n", + " assert_equal(func(''), '')\n", + " assert_equal(func('foo bar'), 'rab oof')\n", + "\n", + "def run_tests(func):\n", + " test = Test()\n", + " test.test_reversed(func)" + ] + }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Algorithm\n", "\n", + "* Convert the string to a list\n", + "* Iterate len(string)/2 times, starting with i = 0:\n", + " * Swap i and len(string) - 1 - i\n", + " * Sncrement i\n", + "* Convert the list to a string and return it\n", + "\n", + "Complexity:\n", + "* Time: O(n)\n", + "* Space: O(n), additional space converting to/from a list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def reverse_string(string):\n", + " if string is None:\n", + " return None\n", + " string_list = list(string)\n", + " string_length = len(string_list)\n", + " for i in xrange(string_length/2):\n", + " string_list[i], string_list[string_length - 1 - i] = \\\n", + " string_list[string_length - 1 - i], string_list[i]\n", + " return ''.join(string_list)\n", + "\n", + "run_tests(reverse_string)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## C Algorithm\n", + "\n", + "This is a classic problem in C/C++\n", + "\n", "We'll want to keep two pointers:\n", "* i is a pointer to the first char\n", "* j is a pointer to the last char\n", @@ -70,7 +140,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Code" + "## C Code" ] }, { @@ -124,24 +194,31 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Pythonic-Code: Not In-Place\n", + "## Pythonic-Code\n", "\n", - "The following code is Pythonic, but requires using additional data structures as Python strings are immutable. You could use a bytearray or a list instead of a string to simulate manipulating an array of characters." + "This question has an artificial constraint that prevented the use of the slice operator and the reversed method. For completeness, the solutions for these are provided below." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def reverse_string_alt(string):\n", + " if string is None:\n", + " return None\n", " return string[::-1]\n", "\n", "def reverse_string_alt2(string):\n", - " return ''.join(reversed(string))" + " if string is None:\n", + " return None \n", + " return ''.join(reversed(string))\n", + "\n", + "run_tests(reverse_string_alt)\n", + "run_tests(reverse_string_alt2)" ] } ],