diff --git a/Sprint-2/implement_skip_list/skip_list.py b/Sprint-2/implement_skip_list/skip_list.py new file mode 100644 index 00000000..34ef5af1 --- /dev/null +++ b/Sprint-2/implement_skip_list/skip_list.py @@ -0,0 +1,74 @@ +import random + +class _Node: + def __init__(self, value, level): + self.value = value + self.forward = [None] * (level + 1) + +class SkipList: + MAX_LEVEL = 16 + P = 0.5 + + def __init__(self): + self.level = 0 + self.head = _Node(None, self.MAX_LEVEL) + + def _random_level(self): + level = 0 + while random.random() < self.P and level < self.MAX_LEVEL: + level += 1 + return level + + def insert(self, value): + update = [None] * (self.MAX_LEVEL + 1) + current = self.head + + for i in range(self.level, -1, -1): + while ( + current.forward[i] is not None + and current.forward[i].value < value + ): + current = current.forward[i] + update[i] = current + + current = current.forward[0] + + if current is not None and current.value == value: + return + + new_level = self._random_level() + + if new_level > self.level: + for i in range(self.level + 1, new_level + 1): + update[i] = self.head + self.level = new_level + + node = _Node(value, new_level) + + for i in range(new_level + 1): + node.forward[i] = update[i].forward[i] + update[i].forward[i] = node + + def __contains__(self, value): + current = self.head + + for i in range(self.level, -1, -1): + while ( + current.forward[i] is not None + and current.forward[i].value < value + ): + current = current.forward[i] + + current = current.forward[0] + + return current is not None and current.value == value + + def to_list(self): + result = [] + current = self.head.forward[0] + + while current is not None: + result.append(current.value) + current = current.forward[0] + + return result \ No newline at end of file diff --git a/Sprint-2/improve_with_precomputing/common_prefix/common_prefix.py b/Sprint-2/improve_with_precomputing/common_prefix/common_prefix.py index f4839e70..564da658 100644 --- a/Sprint-2/improve_with_precomputing/common_prefix/common_prefix.py +++ b/Sprint-2/improve_with_precomputing/common_prefix/common_prefix.py @@ -1,24 +1,38 @@ + from typing import List -def find_longest_common_prefix(strings: List[str]): +def find_longest_common_prefix(strings: List[str]) -> str: """ - find_longest_common_prefix returns the longest string common at the start of any two strings in the passed list. - - In the event that an empty list, a list containing one string, or a list of strings with no common prefixes is passed, the empty string will be returned. + Return the longest common prefix shared by any two strings. + Return an empty string if fewer than two strings are provided + or no non-empty common prefix exists. """ + if len(strings) < 2: + return "" + + # Precompute the sorted order to avoid comparing every pair + ordered_strings = sorted(strings) + longest = "" - for string_index, string in enumerate(strings): - for other_string in strings[string_index+1:]: - common = find_common_prefix(string, other_string) - if len(common) > len(longest): - longest = common + + for index in range(len(ordered_strings) - 1): + common = find_common_prefix( + ordered_strings[index], + ordered_strings[index + 1] + ) + + if len(common) > len(longest): + longest = common + return longest def find_common_prefix(left: str, right: str) -> str: - min_length = min(len(left), len(right)) - for i in range(min_length): - if left[i] != right[i]: - return left[:i] - return left[:min_length] + limit = min(len(left), len(right)) + + for index in range(limit): + if left[index] != right[index]: + return left[:index] + + return left[:limit]