diff --git a/names/bst.py b/names/bst.py new file mode 100644 index 000000000..23a1c3b8f --- /dev/null +++ b/names/bst.py @@ -0,0 +1,126 @@ +import random +""" +Binary search trees are a data structure that enforce an ordering over +the data they store. That ordering in turn makes it a lot more efficient +at searching for a particular piece of data in the tree. + +This part of the project comprises two days: +1. Implement the methods `insert`, `contains`, `get_max`, and `for_each` + on the BSTNode class. +2. Implement the `in_order_print`, `bft_print`, and `dft_print` methods + on the BSTNode class. +""" +class BSTNode: + def __init__(self, value): + self.value = value + self.left = None + self.right = None + + # Insert the given value into the tree + def insert(self, value): + if value < self.value: + if self.left is None: + self.left = BSTNode(value) + else: + self.left.insert(value) + else: + if self.right is None: + self.right = BSTNode(value) + else: + self.right.insert(value) + + # Return True if the tree contains the value + # False if it does not + def contains(self, target): + if target == self.value: + return True + elif target < self.value: + if self.left: + return self.left.contains(target) + else: + return False + elif target > self.value: + if self.right: + return self.right.contains(target) + else: + return False + + # Return the maximum value found in the tree + def get_max(self): + if self: + while self.right is not None: + self = self.right + return self.value + + # recursive method + # if not self.right: + # return self.value + # return self.right.get_max() + + # Call the function `fn` on the value of each node + def for_each(self, fn): + fn(self.value) + + if self.left: + self.left.for_each(fn) + if self.right: + self.right.for_each(fn) + + # Part 2 ----------------------- + + # Print all the values in order from low to high + # Hint: Use a recursive, depth first traversal + def in_order_print(self, node): + if node: + self.in_order_print(node.left) + print(node.value) + self.in_order_print(node.right) + + # Print the value of every node, starting with the given node, + # in an iterative breadth first traversal + def bft_print(self, node): + from collections import deque + + q = deque() + q.append(node) + + while len(q) > 0: + current = q.popleft() + + if current.left: + q.append(current.left) + if current.right: + q.append(current.right) + print(current.value) + + # Print the value of every node, starting with the given node, + # in an iterative depth first traversal + def dft_print(self, node): + stack = [] + stack.append(node) + + while len(stack) > 0: + current = stack.pop() + + if current.right: + stack.append(current.right) + if current.left: + stack.append(current.left) + print(current.value) + + # Stretch Goals ------------------------- + # Note: Research may be required + + # Print Pre-order recursive DFT + def pre_order_dft(self, node): + if node: + print(node.value) + self.pre_order_dft(node.left) + self.pre_order_dft(node.right) + + # Print Post-order recursive DFT + def post_order_dft(self, node): + if node: + self.post_order_dft(node.left) + self.post_order_dft(node.right) + print(node.value) \ No newline at end of file diff --git a/names/names.py b/names/names.py index ea158997f..4bde6ebc1 100644 --- a/names/names.py +++ b/names/names.py @@ -1,4 +1,5 @@ import time +from bst import BSTNode start_time = time.time() @@ -12,11 +13,22 @@ duplicates = [] # Return the list of duplicates in this data structure +# O(n) * O(n) -> O(n^2) # Replace the nested for loops below with your improvements -for name_1 in names_1: - for name_2 in names_2: - if name_1 == name_2: - duplicates.append(name_1) +# for name_1 in names_1: +# for name_2 in names_2: +# if name_1 == name_2: +# duplicates.append(name_1) + +# O(n) + O(n) -> O(2n) +bst = BSTNode("money") + +for n in names_1: + bst.insert(n) + +for n in names_2: + if bst.contains(n): + duplicates.append(n) end_time = time.time() print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") @@ -24,5 +36,5 @@ # ---------- Stretch Goal ----------- # Python has built-in tools that allow for a very efficient approach to this problem -# What's the best time you can accomplish? Thare are no restrictions on techniques or data +# What's the best time you can accomplish? There are no restrictions on techniques or data # structures, but you may not import any additional libraries that you did not write yourself. diff --git a/reverse/reverse.py b/reverse/reverse.py index 6116252d1..e6bd204ac 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -39,4 +39,13 @@ def contains(self, value): return False def reverse_list(self, node, prev): - pass + if node is None: + return None + + if node.next_node == None: + node.next_node = prev + self.head = node + return + + self.reverse_list(node.next_node, node) + node.next_node = prev diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index 37e9fb0dd..dcf630398 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -1,9 +1,16 @@ class RingBuffer: def __init__(self, capacity): - pass + self.index = 0 + self.capacity = capacity + self.storage = [] def append(self, item): - pass + if len(self.storage) == self.capacity: + self.storage[self.index] = item + else: + self.storage.append(item) + + self.index = (self.index + 1) % self.capacity def get(self): - pass \ No newline at end of file + return self.storage \ No newline at end of file