2015-05-03 05:06:21 +08:00
{
" cells " : [
2015-06-18 04:36:55 +08:00
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
2016-07-31 20:11:18 +08:00
" This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://github.com/donnemartin/interactive-coding-challenges). "
2015-07-04 07:56:38 +08:00
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" # Solution Notebook "
2015-06-18 04:36:55 +08:00
]
} ,
2015-05-03 05:06:21 +08:00
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
2016-12-18 20:20:35 +08:00
" ## Problem: Determine if a string is a permutation of another string. \n " ,
2015-05-03 05:06:21 +08:00
" \n " ,
2015-06-30 17:55:58 +08:00
" * [Constraints](#Constraints) \n " ,
2015-05-03 05:06:21 +08:00
" * [Test Cases](#Test-Cases) \n " ,
" * [Algorithm: Compare Sorted Strings](#Algorithm:-Compare-Sorted-Strings) \n " ,
" * [Code: Compare Sorted Strings](#Code:-Compare-Sorted-Strings) \n " ,
2015-05-03 05:10:59 +08:00
" * [Algorithm: Hashmap Lookup](#Algorithm:-Hash-Map-Lookup) \n " ,
2015-06-25 06:22:25 +08:00
" * [Code: Hashmap Lookup](#Code:-Hash-Map-Lookup) \n " ,
" * [Unit Test](#Unit-Test) "
2015-05-03 05:06:21 +08:00
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
2015-06-28 19:13:27 +08:00
" ## Constraints \n " ,
2015-05-03 05:06:21 +08:00
" \n " ,
2015-07-04 07:56:38 +08:00
" * Can we assume the string is ASCII? \n " ,
2015-06-25 06:22:25 +08:00
" * Yes \n " ,
" * Note: Unicode strings could require special handling depending on your language \n " ,
2015-05-03 05:06:21 +08:00
" * Is whitespace important? \n " ,
" * Yes \n " ,
" * Is this case sensitive? ' Nib ' , ' bin ' is not a match? \n " ,
2016-06-05 19:18:14 +08:00
" * Yes \n " ,
" * Can we use additional data structures? \n " ,
" * Yes \n " ,
" * Can we assume this fits in memory? \n " ,
2015-05-03 05:06:21 +08:00
" * Yes "
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" ## Test Cases \n " ,
" \n " ,
2016-06-05 19:18:14 +08:00
" * One or more None inputs -> False \n " ,
2015-05-03 05:06:21 +08:00
" * One or more empty strings -> False \n " ,
" * ' Nib ' , ' bin ' -> False \n " ,
" * ' act ' , ' cat ' -> True \n " ,
2017-04-04 17:58:53 +08:00
" * ' a ct ' , ' ca t ' -> True \n " ,
" * ' dog ' , ' doggo ' -> False "
2015-05-03 05:06:21 +08:00
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" ## Algorithm: Compare Sorted Strings \n " ,
" \n " ,
2015-07-05 21:03:19 +08:00
" Permutations contain the same strings but in different orders. This approach could be slow for large strings due to sorting. \n " ,
2015-05-03 05:06:21 +08:00
" \n " ,
" * Sort both strings \n " ,
" * If both sorted strings are equal \n " ,
" * return True \n " ,
" * Else \n " ,
" * return False \n " ,
" \n " ,
" Complexity: \n " ,
" * Time: O(n log n) from the sort, in general \n " ,
2015-07-05 21:03:19 +08:00
" * Space: O(n) "
2015-05-03 05:06:21 +08:00
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" ## Code: Compare Sorted Strings "
]
} ,
{
" cell_type " : " code " ,
2015-06-25 06:22:25 +08:00
" execution_count " : 1 ,
2020-07-04 22:56:49 +08:00
" metadata " : { } ,
2015-05-03 05:06:21 +08:00
" outputs " : [ ] ,
" source " : [
2016-08-13 18:39:19 +08:00
" class Permutations(object): \n " ,
" \n " ,
" def is_permutation(self, str1, str2): \n " ,
" if str1 is None or str2 is None: \n " ,
" return False \n " ,
" return sorted(str1) == sorted(str2) "
2015-05-03 05:06:21 +08:00
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" ## Algorithm: Hash Map Lookup \n " ,
" \n " ,
" We ' ll keep a hash map (dict) to keep track of characters we encounter. \n " ,
" \n " ,
" Steps: \n " ,
" * Scan each character \n " ,
" * For each character in each string: \n " ,
" * If the character does not exist in a hash map, add the character to a hash map \n " ,
" * Else, increment the character ' s count \n " ,
" * If the hash maps for each string are equal \n " ,
" * Return True \n " ,
" * Else \n " ,
" * Return False \n " ,
" \n " ,
" Notes: \n " ,
2015-06-25 06:22:25 +08:00
" * Since the characters are in ASCII, we could potentially use an array of size 128 (or 256 for extended ASCII), where each array index is equivalent to an ASCII value \n " ,
2015-05-03 05:06:21 +08:00
" * Instead of using two hash maps, you could use one hash map and increment character values based on the first string and decrement based on the second string \n " ,
2015-07-04 07:56:38 +08:00
" * You can short circuit if the lengths of each string are not equal, although len() in Python is generally O(1) unlike other languages like C where getting the length of a string is O(n) \n " ,
2015-05-03 05:06:21 +08:00
" \n " ,
" Complexity: \n " ,
" * Time: O(n) \n " ,
2015-07-05 21:03:19 +08:00
" * Space: O(n) "
2015-05-03 05:06:21 +08:00
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
2015-05-03 05:10:59 +08:00
" ## Code: Hash Map Lookup "
2015-05-03 05:06:21 +08:00
]
} ,
{
" cell_type " : " code " ,
2015-06-25 06:22:25 +08:00
" execution_count " : 2 ,
2020-07-04 22:56:49 +08:00
" metadata " : { } ,
2015-05-03 05:06:21 +08:00
" outputs " : [ ] ,
" source " : [
" from collections import defaultdict \n " ,
" \n " ,
2015-07-04 07:56:38 +08:00
" \n " ,
2016-08-13 18:39:19 +08:00
" class PermutationsAlt(object): \n " ,
" \n " ,
" def is_permutation(self, str1, str2): \n " ,
" if str1 is None or str2 is None: \n " ,
" return False \n " ,
" if len(str1) != len(str2): \n " ,
" return False \n " ,
" unique_counts1 = defaultdict(int) \n " ,
" unique_counts2 = defaultdict(int) \n " ,
" for char in str1: \n " ,
" unique_counts1[char] += 1 \n " ,
" for char in str2: \n " ,
" unique_counts2[char] += 1 \n " ,
" return unique_counts1 == unique_counts2 "
2015-06-25 06:22:25 +08:00
]
} ,
{
" cell_type " : " markdown " ,
" metadata " : { } ,
" source " : [
" ## Unit Test "
]
} ,
{
" cell_type " : " code " ,
" execution_count " : 3 ,
2020-07-04 22:56:49 +08:00
" metadata " : { } ,
2015-06-25 06:22:25 +08:00
" outputs " : [
{
" name " : " stdout " ,
" output_type " : " stream " ,
" text " : [
2015-07-04 07:56:38 +08:00
" Overwriting test_permutation_solution.py \n "
2015-06-25 06:22:25 +08:00
]
}
] ,
" source " : [
2015-07-04 07:56:38 +08:00
" %% writefile test_permutation_solution.py \n " ,
2020-07-04 22:56:49 +08:00
" import unittest \n " ,
2015-05-03 05:06:21 +08:00
" \n " ,
2015-07-04 07:56:38 +08:00
" \n " ,
2020-07-04 22:56:49 +08:00
" class TestPermutation(unittest.TestCase): \n " ,
2015-07-12 03:34:14 +08:00
" \n " ,
2015-06-25 06:22:25 +08:00
" def test_permutation(self, func): \n " ,
2020-07-04 22:56:49 +08:00
" self.assertEqual(func(None, ' foo ' ), False) \n " ,
" self.assertEqual(func( ' ' , ' foo ' ), False) \n " ,
" self.assertEqual(func( ' Nib ' , ' bin ' ), False) \n " ,
" self.assertEqual(func( ' act ' , ' cat ' ), True) \n " ,
" self.assertEqual(func( ' a ct ' , ' ca t ' ), True) \n " ,
" self.assertEqual(func( ' dog ' , ' doggo ' ), False) \n " ,
2015-06-25 06:22:25 +08:00
" print( ' Success: test_permutation ' ) \n " ,
" \n " ,
2015-07-12 03:34:14 +08:00
" \n " ,
2015-07-04 07:56:38 +08:00
" def main(): \n " ,
" test = TestPermutation() \n " ,
2016-08-13 18:39:19 +08:00
" permutations = Permutations() \n " ,
" test.test_permutation(permutations.is_permutation) \n " ,
2015-07-04 07:56:38 +08:00
" try: \n " ,
2016-08-13 18:39:19 +08:00
" permutations_alt = PermutationsAlt() \n " ,
" test.test_permutation(permutations_alt.is_permutation) \n " ,
2015-07-04 07:56:38 +08:00
" except NameError: \n " ,
" # Alternate solutions are only defined \n " ,
" # in the solutions file \n " ,
" pass \n " ,
2015-07-12 03:34:14 +08:00
" \n " ,
" \n " ,
2015-07-04 07:56:38 +08:00
" if __name__ == ' __main__ ' : \n " ,
" main() "
]
} ,
{
" cell_type " : " code " ,
" execution_count " : 4 ,
2020-07-04 22:56:49 +08:00
" metadata " : { } ,
2015-07-04 07:56:38 +08:00
" outputs " : [
{
" name " : " stdout " ,
" output_type " : " stream " ,
" text " : [
2016-08-13 18:39:19 +08:00
" Success: test_permutation \n " ,
2015-07-04 07:56:38 +08:00
" Success: test_permutation \n "
]
}
] ,
" source " : [
" run -i test_permutation_solution.py "
2015-05-03 05:06:21 +08:00
]
}
] ,
" metadata " : {
" kernelspec " : {
2016-02-10 19:29:50 +08:00
" display_name " : " Python 3 " ,
2015-05-03 05:06:21 +08:00
" language " : " python " ,
2016-02-10 19:29:50 +08:00
" name " : " python3 "
2015-05-03 05:06:21 +08:00
} ,
" language_info " : {
" codemirror_mode " : {
" name " : " ipython " ,
2016-02-10 19:29:50 +08:00
" version " : 3
2015-05-03 05:06:21 +08:00
} ,
" file_extension " : " .py " ,
" mimetype " : " text/x-python " ,
" name " : " python " ,
" nbconvert_exporter " : " python " ,
2016-02-10 19:29:50 +08:00
" pygments_lexer " : " ipython3 " ,
2020-07-04 22:56:49 +08:00
" version " : " 3.7.2 "
2015-05-03 05:06:21 +08:00
}
} ,
" nbformat " : 4 ,
2020-07-04 22:56:49 +08:00
" nbformat_minor " : 1
2015-05-03 05:06:21 +08:00
}