Skip to content

Commit a7fac87

Browse files
authored
Merge pull request #1 from abravebee/mvp
MVP
2 parents 1262f36 + 5efce71 commit a7fac87

File tree

5 files changed

+202
-7
lines changed

5 files changed

+202
-7
lines changed

Data_Structures_Answers.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
Add your answers to the questions below.
22

33
1. What is the runtime complexity of your ring buffer's `append` method?
4+
O(n) because the for loop runs linearly based on the capacity input to the class.
45

56
2. What is the space complexity of your ring buffer's `append` function?
7+
O(1) because the capacity is always the same and we're not adding extra space when appending values, only replacing space already taken up.
68

79
3. What is the runtime complexity of your ring buffer's `get` method?
10+
O(n) because we have another for loop going through the whole storage.
811

912
4. What is the space complexity of your ring buffer's `get` method?
10-
13+
O(n) because the result array grows depending upon the values in storage.
1114

1215
5. What is the runtime complexity of the provided code in `names.py`?
16+
O(n^2) for nested for loops.
1317

1418
6. What is the space complexity of the provided code in `names.py`?
19+
O(n) because the duplicates array grows based on the values in the inputs.
1520

1621
7. What is the runtime complexity of your optimized code in `names.py`?
22+
O(n log n) because binary search trees are lovely, but we also have to search it for every element in names_2.
1723

1824
8. What is the space complexity of your optimized code in `names.py`?
25+
O(n^2) because I have to store all the names_1 values in the tree and then the duplicates array also grows based on input.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Sprint Challenge: Data Structures
2-
2+
33
In this week's Sprint you implemented some classic and fundamental data structures and learned about how to go about evaluating their respective runtimes and performance. This Sprint Challenge aims to assess your comfort with these topics through exercises that build on the data structures you implemented and the algorithmic intuition you've started to build up.
44

55
## Instructions

names/binary_search.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
class BinarySearchTree:
2+
def __init__(self, value):
3+
self.value = value
4+
self.left = None
5+
self.right = None
6+
7+
def insert(self, value):
8+
if value < self.value:
9+
if not self.left:
10+
self.left = BinarySearchTree(value)
11+
else:
12+
self.left.insert(value)
13+
14+
elif value >= self.value:
15+
if not self.right:
16+
self.right = BinarySearchTree(value)
17+
else:
18+
self.right.insert(value)
19+
pass
20+
21+
# searches the binary search tree for the input value, returning a boolean indicating whether the value exists in the tree or not.
22+
def contains(self, target):
23+
# compare target to root
24+
if target == self.value:
25+
print(f"target {target} == self.value {self.value}")
26+
return True
27+
# if it's smaller, check left side
28+
elif target < self.value:
29+
print(f"target {target} < self.value {self.value}")
30+
# first check that there is a left side; if not, return False
31+
if not self.left:
32+
print("no self.left")
33+
return False
34+
# else, if it doesn't match the left side, call contains on left side with same target
35+
elif target != self.left:
36+
print(f"target {target} != self.left {self.left}")
37+
return self.left.contains(target)
38+
else:
39+
print(f"target {target} == self.left {self.left}")
40+
return True
41+
# else, check right side
42+
elif target > self.value:
43+
print(f"target {target} > self.value {self.value}")
44+
# first check that there is a right side; if not, return False
45+
if not self.right:
46+
print("no self.right")
47+
return False
48+
# else, if it doesn't match the right side, call contains on right side with same target
49+
elif target != self.right:
50+
print(f"target {target} != self.right {self.right}")
51+
return self.right.contains(target)
52+
else:
53+
print(f"target {target} == self.right {self.right}")
54+
return True
55+
pass
56+
57+
# returns the maximum value in the binary search tree.
58+
def get_max(self):
59+
# find rightmost node
60+
max = self
61+
while max.right:
62+
max = max.right
63+
return max.value
64+
pass
65+
66+
# performs a traversal of _every_ node in the tree, executing the passed-in callback function on each tree node value.
67+
# There is a myriad of ways to perform tree traversal; in this case any of them should work.
68+
def for_each(self, cb):
69+
Inorder
70+
if self:
71+
if self.left:
72+
self.left.for_each(cb)
73+
cb(self.value)
74+
if self.right:
75+
self.right.for_each(cb)
76+

names/names.py

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,73 @@
1010
names_2 = f.read().split("\n") # List containing 10000 names
1111
f.close()
1212

13+
class BinarySearchTree:
14+
def __init__(self, value):
15+
self.value = value
16+
self.left = None
17+
self.right = None
18+
19+
def insert(self, value):
20+
if value < self.value:
21+
if not self.left:
22+
self.left = BinarySearchTree(value)
23+
else:
24+
self.left.insert(value)
25+
26+
elif value >= self.value:
27+
if not self.right:
28+
self.right = BinarySearchTree(value)
29+
else:
30+
self.right.insert(value)
31+
pass
32+
33+
# searches the binary search tree for the input value, returning a boolean indicating whether the value exists in the tree or not.
34+
def contains(self, target):
35+
# compare target to root
36+
if target == self.value:
37+
return True
38+
# if it's smaller, check left side
39+
elif target < self.value:
40+
# first check that there is a left side; if not, return False
41+
if not self.left:
42+
return False
43+
# else, if it doesn't match the left side, call contains on left side with same target
44+
elif target != self.left:
45+
return self.left.contains(target)
46+
else:
47+
return True
48+
# else, check right side
49+
elif target > self.value:
50+
# first check that there is a right side; if not, return False
51+
if not self.right:
52+
return False
53+
# else, if it doesn't match the right side, call contains on right side with same target
54+
elif target != self.right:
55+
return self.right.contains(target)
56+
else:
57+
return True
58+
pass
59+
60+
1361
duplicates = []
14-
for name_1 in names_1:
15-
for name_2 in names_2:
16-
if name_1 == name_2:
17-
duplicates.append(name_1)
62+
63+
# ~20 seconds
64+
# for name_1 in names_1:
65+
# for name_2 in names_2:
66+
# if name_1 == name_2:
67+
# duplicates.append(name_1)
68+
69+
# ~0.33 seconds!!
70+
# plug in first value to root
71+
tree = BinarySearchTree(names_1[0])
72+
# add first file's names to tree
73+
for name in names_1:
74+
tree.insert(name)
75+
for name in names_2:
76+
# use contain search function to find duplicates
77+
if tree.contains(name):
78+
# add duplicates to list
79+
duplicates.append(name)
1880

1981
end_time = time.time()
2082
print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n")

ring_buffer/ring_buffer.py

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,57 @@ def __init__(self, capacity):
55
self.storage = [None]*capacity
66

77
def append(self, item):
8+
length = len(self.storage)
9+
#if the current storage is at capacity
10+
for i in range (0, length):
11+
if self.storage[i] == None:
12+
self.storage[i] = item
13+
print(f"for i self.storage: {self.storage}")
14+
return
15+
#append to current oldest index
16+
self.storage[self.current] = item
17+
#next index is now the oldest
18+
if self.current == self.capacity-1:
19+
self.current = 0
20+
else:
21+
self.current += 1
822
pass
923

1024
def get(self):
11-
pass
25+
# have a result array
26+
result = []
27+
# for each element
28+
for element in self.storage:
29+
# check that element is not none
30+
if element is not None:
31+
# append to result array
32+
result.append(element)
33+
# return array
34+
return result
35+
pass
36+
37+
buffer = RingBuffer(3)
38+
39+
print(buffer.get()) # should return []
40+
41+
buffer.append('a')
42+
buffer.append('b')
43+
buffer.append('c')
44+
45+
print(buffer.get()) # should return ['a', 'b', 'c']
46+
47+
# 'd' overwrites the oldest value in the ring buffer, which is 'a'
48+
buffer.append('d')
49+
50+
print(buffer.get()) # should return ['d', 'b', 'c']
51+
52+
buffer.append('e')
53+
buffer.append('f')
54+
55+
print(buffer.get()) # should return ['d', 'e', 'f']
56+
57+
buffer.append('g')
58+
buffer.append('h')
59+
buffer.append('i')
60+
61+
print(buffer.get())

0 commit comments

Comments
 (0)