Reworked algorithm descriptions. Added notebook index. Minor cleanup.

This commit is contained in:
Donne Martin
2015-05-02 17:14:29 -04:00
parent e22f7b8d20
commit d546ea49b4

View File

@@ -4,7 +4,16 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Problem: Implement an algorithm to determine if a string has all unique characters" "## Problem: Implement an algorithm to determine if a string has all unique characters\n",
"\n",
"* [Clarifying Questions](#Clarifying-Questions)\n",
"* [Test Cases](#Test-Cases)\n",
"* [Algorithm 1: Sets and Length Comparison](#Algorithm-1:-Sets-and-Length-Comparison)\n",
"* [Code: Sets and Length Comparison](#Code:-Sets-and-Length-Comparison)\n",
"* [Algorithm 2: Hash Map Lookup](#Algorithm-2:-Hash-Map-Lookup)\n",
"* [Code: Hash Map Lookup](#Code:-Hash-Map-Lookup)\n",
"* [Algorithm 3: In-Place](#Algorithm-3:-In-Place)\n",
"* [Code: In-Place](#Code:-In-Place)"
] ]
}, },
{ {
@@ -13,7 +22,7 @@
"source": [ "source": [
"## Clarifying Questions\n", "## Clarifying Questions\n",
"* Is the string in ASCII (extended?) or Unicode? \n", "* Is the string in ASCII (extended?) or Unicode? \n",
" * ASCII extended, which is 256 characters.\n", " * ASCII extended, which is 256 characters\n",
"* Can you use additional data structures? \n", "* Can you use additional data structures? \n",
" * Yes" " * Yes"
] ]
@@ -24,40 +33,34 @@
"source": [ "source": [
"## Test Cases\n", "## Test Cases\n",
"\n", "\n",
"* \"\" -> True\n", "* '' -> True\n",
"* \"foo\" -> False\n", "* 'foo' -> False\n",
"* \"bar\" -> True" "* 'bar' -> True"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Algorithm\n", "## Algorithm 1: Sets and Length Comparison\n",
"\n", "\n",
"We'll keep a hash map (set) to keep track of unique characters we encounter. \n", "A set is an unordered collection of unique elements. \n",
"\n",
"Note:\n",
"* We could also use a dictionary, but it seems more logical to use a set as it does not contain duplicate elements.\n",
"* Since the characters are in ASCII, we could potentially use an array of size 128 (or 256 for extended ASCII)\n",
"\n",
"Steps:\n",
"* Scan each character.\n",
"* For each character:\n",
" * If the character does not exist in a hash map, add the character to a hash map.\n",
" * Else, return False.\n",
"* Return True\n",
"\n", "\n",
"* If the length of the set(string) equals the length of the string\n",
" * Return True\n",
"* Else\n",
" * Return False\n",
" \n",
"Complexity:\n", "Complexity:\n",
"* Time: O(n).\n", "* Time: O(n)\n",
"* Space: Additional O(m), where m is the number of unique characters in the hash map." "* Space: Additional O(m), where m is the number of unique characters in the set"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Code" "## Code: Sets and Length Comparison"
] ]
}, },
{ {
@@ -69,13 +72,7 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"def unique_chars(string):\n", "def unique_chars(string):\n",
" chars_set = set()\n", " return len(set(string)) == len(string)\n",
" for char in string:\n",
" if char in chars_set:\n",
" return False\n",
" else:\n",
" chars_set.add(char)\n",
" return True\n",
"\n", "\n",
"print(unique_chars(''))\n", "print(unique_chars(''))\n",
"print(unique_chars('foo'))\n", "print(unique_chars('foo'))\n",
@@ -86,10 +83,59 @@
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Algorithm: No Additional Data Structures\n", "## Algorithm 2: Hash Map Lookup\n",
"\n",
"We'll keep a hash map (set) to keep track of unique characters we encounter. \n",
"\n",
"Steps:\n",
"* Scan each character\n",
"* For each character:\n",
" * If the character does not exist in a hash map, add the character to a hash map\n",
" * Else, return False\n",
"* Return True\n",
"\n",
"Notes:\n",
"* We could also use a dictionary, but it seems more logical to use a set as it does not contain duplicate elements\n",
"* Since the characters are in ASCII, we could potentially use an array of size 128 (or 256 for extended ASCII)\n",
"\n",
"Complexity:\n",
"* Time: O(n)\n",
"* Space: Additional O(m), where m is the number of unique characters in the hash map"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Code: Hash Map Lookup"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def unique_chars_alt(string):\n",
" chars_set = set()\n",
" for char in string:\n",
" if char in chars_set:\n",
" return False\n",
" else:\n",
" chars_set.add(char)\n",
" return True"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Algorithm 3: In-Place\n",
"\n", "\n",
"Since we cannot use additional data structures, this will eliminate the fast lookup O(1) time provided by our hash map.\n", "Since we cannot use additional data structures, this will eliminate the fast lookup O(1) time provided by our hash map.\n",
"* Scan each character.\n", "* Scan each character\n",
"* For each character:\n", "* For each character:\n",
" * Scan all [other] characters in the array\n", " * Scan all [other] characters in the array\n",
" * Exluding the current character from the scan is rather tricky in Python and results in a non-Pythonic solution\n", " * Exluding the current character from the scan is rather tricky in Python and results in a non-Pythonic solution\n",
@@ -97,15 +143,15 @@
"* Return True\n", "* Return True\n",
"\n", "\n",
"Algorithm Complexity:\n", "Algorithm Complexity:\n",
"* Time: O(n^2).\n", "* Time: O(n^2)\n",
"* Space: In-place." "* Space: In-place"
] ]
}, },
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": {}, "metadata": {},
"source": [ "source": [
"## Code" "## Code: In-Place"
] ]
}, },
{ {
@@ -122,25 +168,6 @@
" return False\n", " return False\n",
" return True" " return True"
] ]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Pythonic Solution(s)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def unique_chars_alt2(string):\n",
" return len(set(string)) == len(string)"
]
} }
], ],
"metadata": { "metadata": {