From 566e882cbcbc5efac426d4d65c2e3778d9eb68df Mon Sep 17 00:00:00 2001 From: Jeffrey Ugochukwu <44630324+JeffTheAggie@users.noreply.github.com> Date: Fri, 3 Apr 2020 17:33:30 -0700 Subject: [PATCH 1/5] Update 9.md Give a more detailed description with how the interview question works and left comments in the code to explain the parts of the code. --- .../Activity2_HashTables/cards/9.md | 93 ++++++++++++++----- 1 file changed, 69 insertions(+), 24 deletions(-) diff --git a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md index c44607a7..1dd136f2 100644 --- a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md +++ b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md @@ -4,38 +4,83 @@ **Example Output**: - Input: "abcabcbb" - Output: 3 - Explanation: The answer is "abc", with the length of 3. + Input: "ABDEFGABEF" + Output: The input string is ABDEFGABEF The length of the longest non-repeating character substring is 6 + Explanation: The answer is "BDEFGA" and “DEFGAB”, with the length of 6. **Solution**: Concept: - The idea on how to approach this problem is to define the appropriate mapping of each character in your string based on it's index. - This would skip repeated characters in the string to improve the run time of this algorithm. This would result of a time complexity of - O(n), a space complexity for the Hashmap of O(min(m,n)), and a space complexity for the table of O(m) * m. + The solution uses extra space to store the last indexes of already visited characters. The idea is to scan the string from left to right, keep track of the maximum length Non-Repeating Character Substring (NRCS) seen so far. Let the maximum length be max_len. When we traverse the string, we also keep track of the length of the current NRCS using cur_len variable. For every new character, we look for it in already processed part of the string (A temp array called visited[] is used for this purpose). If it is not present, then we increase the cur_len by 1. If present, then there are two cases: + +The previous instance of character is not part of current NRCS (The NRCS which is under process). In this case, we need to simply increase cur_len by 1. +If the previous instance is part of the current NRCS, then our current NRCS changes. It becomes the substring starting from the next character of the previous instance to currently scanned character. We also need to compare cur_len and max_len, before changing current NRCS (or changing cur_len). + +The time complexity is O(n + d) where n is length of the input string and d is number of characters in input string alphabet. For example, if string consists of lowercase English characters then value of d is 26. Code: ```python - def lengthOfLongestSubstring(self, s: 'str') -> 'int': - maxlen = 0 - currentlen = 0 - indHash = {} - leftside = -1 - ls = len(s) - for ind, ch in enumerate(s): - if (ch in indHash) and (leftside < indHash[ch]): - leftside = indHash[ch]; - currentlen = ind - leftside; - if currentlen > maxlen: - maxlen = currentlen - indHash[ch] = ind - currentlen = ls - leftside - 1 - if currentlen > maxlen: - maxlen = currentlen - return maxlen + # Python program to find the length of the longest substring +# without repeating characters +NO_OF_CHARS = 256 + +def longestUniqueSubsttr(string): + n = len(string) + cur_len = 1 # To store the length of current substring + max_len = 1 # To store the result + prev_index = 0 # To store the previous index + i = 0 + + # Initialize the visited array as -1, -1 is used to indicate + # that character has not been visited yet. + visited = [-1] * NO_OF_CHARS + + # Mark first character as visited by storing the index of + # first character in visited array. + visited[ord(string[0])] = 0 + + # Start from the second character. First character is already + # processed (cur_len and max_len are initialized as 1, and + # visited[str[0]] is set + for i in xrange(1, n): + prev_index = visited[ord(string[i])] + + # If the currentt character is not present in the already + # processed substring or it is not part of the current NRCS, + # then do cur_len++ + if prev_index == -1 or (i - cur_len > prev_index): + cur_len+= 1 + + # If the current character is present in currently considered + # NRCS, then update NRCS to start from the next character of + # previous instance. + else: + # Also, when we are changing the NRCS, we should also + # check whether length of the previous NRCS was greater + # than max_len or not. + if cur_len > max_len: + max_len = cur_len + + cur_len = i - prev_index + + # update the index of current character + visited[ord(string[i])] = i + + # Compare the length of last NRCS with max_len and update + # max_len if needed + if cur_len > max_len: + max_len = cur_len + + return max_len + +# Driver program to test the above function +string = "ABDEFGABEF" +print "The input string is " + string +length = longestUniqueSubsttr(string) +print ("The length of the longest non-repeating character" + + " substring is " + str(length)) ``` - \ No newline at end of file + From 3d7500f6cddbe715747d0dbbe8a8dc19b0b33c25 Mon Sep 17 00:00:00 2001 From: Jeffrey Ugochukwu <44630324+JeffTheAggie@users.noreply.github.com> Date: Fri, 3 Apr 2020 17:57:21 -0700 Subject: [PATCH 2/5] Create 9-Checkpoint.md Made a checkpoint for the leetcode question card --- .../Activity2_HashTables/checkpoints/9-Checkpoint.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md diff --git a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md new file mode 100644 index 00000000..ac5376b6 --- /dev/null +++ b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md @@ -0,0 +1,12 @@ +# name +Run time of "Length of the longest substring without repeating characters" + +# cards_folder +curriculum/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/ + +# instruction +What is the run time for the "Length of the longest substring without repeating characters" interview question and also explain +your reasoning behind the run time? + +# checkpoint_type +Short Answer From c1ce8cb1fbd0b85dfcefa3f46aff518635f50280 Mon Sep 17 00:00:00 2001 From: Jeffrey Ugochukwu <44630324+JeffTheAggie@users.noreply.github.com> Date: Fri, 3 Apr 2020 18:03:18 -0700 Subject: [PATCH 3/5] Update 9.md Added a general definition for the time complexity --- .../Activity2_HashTables/cards/9.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md index 1dd136f2..6b854f82 100644 --- a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md +++ b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md @@ -16,7 +16,7 @@ The previous instance of character is not part of current NRCS (The NRCS which is under process). In this case, we need to simply increase cur_len by 1. If the previous instance is part of the current NRCS, then our current NRCS changes. It becomes the substring starting from the next character of the previous instance to currently scanned character. We also need to compare cur_len and max_len, before changing current NRCS (or changing cur_len). -The time complexity is O(n + d) where n is length of the input string and d is number of characters in input string alphabet. For example, if string consists of lowercase English characters then value of d is 26. +The time complexity is O(n + d) (generally, O(n)) where n is length of the input string and d is number of characters in input string alphabet. For example, if string consists of lowercase English characters then value of d is 26. From fed92436e6770962509000ccef9805d246f425f6 Mon Sep 17 00:00:00 2001 From: Jeffrey Ugochukwu <44630324+JeffTheAggie@users.noreply.github.com> Date: Sat, 4 Apr 2020 02:50:44 -0700 Subject: [PATCH 4/5] Update 9.md Added more logistical explanations that would explain the concept behind the LeetCode question and tied back to its importance to hashtables. --- .../Activity2_HashTables/cards/9.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md index 6b854f82..a7974b42 100644 --- a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md +++ b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/cards/9.md @@ -11,13 +11,16 @@ **Solution**: Concept: - The solution uses extra space to store the last indexes of already visited characters. The idea is to scan the string from left to right, keep track of the maximum length Non-Repeating Character Substring (NRCS) seen so far. Let the maximum length be max_len. When we traverse the string, we also keep track of the length of the current NRCS using cur_len variable. For every new character, we look for it in already processed part of the string (A temp array called visited[] is used for this purpose). If it is not present, then we increase the cur_len by 1. If present, then there are two cases: + The solution uses extra space to store the last indices of already visited characters. The reason why we would store the last indices of the already visited characters is because we want our code to realize that when it iterates through the string of charcaters, it knows the location of the unique substring that we have found. As it goes through the string, it knows that we have seen this string before when looking at a different index so that we don't put 2 of the same strings in one list to give an inaccurate size for the maximum length. The idea is to scan the string from left to right, keep track of the maximum length Non-Repeating Character Substring (NRCS) seen so far. We should keep track of the maximum length for the NRCS since we want to have the most accurate value when displaying the storage. Let the maximum length be `max_len`. This would store the result of the complete length of the maximum amount of NRCS's possible after we completely iterate through the string. We initialize our `max_len` with a size of 1 since this would be later updated whenever we store a new amount of NRCS's to be added into `max_len`. This would keep `max_len` to be consistent in terms of having the largest amount of NRCS's to accurately answer the question. When we traverse the string, we also keep track of the length of the current NRCS using `cur_len` variable. For every new character, we look for it in an already processed part of the string (A temp array called `visited[]` is used for this purpose). If it is not present, then we increase the `cur_len` by 1. If present, then there are two cases: -The previous instance of character is not part of current NRCS (The NRCS which is under process). In this case, we need to simply increase cur_len by 1. -If the previous instance is part of the current NRCS, then our current NRCS changes. It becomes the substring starting from the next character of the previous instance to currently scanned character. We also need to compare cur_len and max_len, before changing current NRCS (or changing cur_len). +- The previous instance of character is not part of current NRCS (The NRCS which is under process). In this case, we need to simply increase `cur_len` by 1. +- If the previous instance is part of the current NRCS, then our current NRCS changes. It becomes the substring starting from the next character of the previous instance to currently scanned character. We also need to compare `cur_len` and `max_len`, before changing current NRCS (or changing cur_len). Once we have realized that the size of `cur_len` is greater than the size of `max_len`, then we set consistently set `cur_len` equal to `max_len` because this would consistently make `max_len` have the highest amount of NRCS's since that's what the variable would serve for this problem. -The time complexity is O(n + d) (generally, O(n)) where n is length of the input string and d is number of characters in input string alphabet. For example, if string consists of lowercase English characters then value of d is 26. +This would mean that we're actually breaking down the string into two parts: one part of the string where we have vistited the NRCS's that we have found previously and another part where we find a new NRCS that we will store to `cur_len` to update to `max_len` eventually. +This problem relates to hashtables in which we have to use linear probing to appropriately organize the NRCS's into `max_len`. Since we know that everytime `cur_len` notices an NRCS that was already visited, it would go to the next index to find a new NRCS to add to the list size of `cur_len`, which will update `max_len`. This implements the use of a skip value in which when we do a modulo division for the hash value, which results in creating the index value as a location to input our hash value. Once we see that the slot is full, we implement a skip value until we find the next availble slot. It's a similar concept here where if we found a unique NRCS, we add it to `cur_len`. If we find the same NRCS, then we skip the index by 1 until we find a new one. + +The time complexity is O(n + d) (generally, O(n)) where n is length of the input string and d is number of characters in input string alphabet (d is treated as a constant in this case). O(n) would be the continuous iteration through the string to find a unique NRCS and O(d) (really, it's O(1)) would be the constant in which you add each new NRCS into `max_len` given that `cur_len` is greater than `max_len`. For example, if the string consists of lowercase English characters then value of d is 26. The space complexity would be O(d) (generally O(1)) since you're adding a consistent amount of charcaters to increase the storage size of `max_len`. Code: From 22586cd9a838842001c2d883efaecd5d8251155f Mon Sep 17 00:00:00 2001 From: Jeffrey Ugochukwu <44630324+JeffTheAggie@users.noreply.github.com> Date: Sat, 4 Apr 2020 02:52:53 -0700 Subject: [PATCH 5/5] Update 9-Checkpoint.md Reworded instruction for checkpoint --- .../Activity2_HashTables/checkpoints/9-Checkpoint.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md index ac5376b6..c06e4368 100644 --- a/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md +++ b/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/9-Checkpoint.md @@ -5,8 +5,8 @@ Run time of "Length of the longest substring without repeating characters" curriculum/Data-Structures-and-Algos-Topic/Module1-Intro-to-Data-Structures-and-Algos/Activity2_HashTables/checkpoints/ # instruction -What is the run time for the "Length of the longest substring without repeating characters" interview question and also explain -your reasoning behind the run time? +Find and explain the run time of the algorithm for the "Length of the longest substring without repeating characters" interview question. + # checkpoint_type Short Answer