From 3c38fa80503f09569746d283f3d03932aa0ff7dd Mon Sep 17 00:00:00 2001 From: kyranmccann Date: Tue, 26 Feb 2019 13:06:45 -0800 Subject: [PATCH 1/5] update answers --- Data_Structures_Questions.md | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Data_Structures_Questions.md b/Data_Structures_Questions.md index bf10552507..e4d4d4a049 100644 --- a/Data_Structures_Questions.md +++ b/Data_Structures_Questions.md @@ -3,7 +3,7 @@ Answer the following questions for each of the data structures you implemented a ## Queue 1. What is the runtime complexity of `enqueue`? -O(n) +O(1) 2. What is the runtime complexity of `dequeue`? 0(1) @@ -13,43 +13,47 @@ O(1) ## Binary Search Tree 1. What is the runtime complexity of `insert`? +O(log(n)) 2. What is the runtime complexity of `contains`? - +O(log(n)) 3. What is the runtime complexity of `get_max`? - +O(log(n)) ## Heap 1. What is the runtime complexity of `_bubble_up`? - +O(log(n)) 2. What is the runtime complexity of `_sift_down`? - +O(log(n)) 3. What is the runtime complexity of `insert`? - +O(log(n)) 4. What is the runtime complexity of `delete`? - +O(log(n)) 5. What is the runtime complexity of `get_max`? - +O(1) ## Doubly Linked List 1. What is the runtime complexity of `ListNode.insert_after`? - +O(1) 2. What is the runtime complexity of `ListNode.insert_before`? +O(1) 3. What is the runtime complexity of `ListNode.delete`? +O(1) 4. What is the runtime complexity of `DoublyLinkedList.add_to_head`? +O(1) 5. What is the runtime complexity of `DoublyLinkedList.remove_from_head`? - +O(1) 6. What is the runtime complexity of `DoublyLinkedList.add_to_tail`? - +O(1) 7. What is the runtime complexity of `DoublyLinkedList.remove_from_tail`? - +O(1) 8. What is the runtime complexity of `DoublyLinkedList.move_to_front`? - +O(1) 9. What is the runtime complexity of `DoublyLinkedList.move_to_end`? - +O(1) 10. What is the runtime complexity of `DoublyLinkedList.delete`? - +O(1) a. Compare the runtime of the doubly linked list's `delete` method with the worst-case runtime of the JS `Array.splice` method. Which method generally performs better? From 84292e6c4baed09e8b4a704f5da519fc39bbbc4d Mon Sep 17 00:00:00 2001 From: kyranmccann Date: Tue, 26 Feb 2019 22:30:17 -0800 Subject: [PATCH 2/5] working on delete --- doubly_linked_list/doubly_linked_list.py | 66 +++++++++++++++++++----- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/doubly_linked_list/doubly_linked_list.py b/doubly_linked_list/doubly_linked_list.py index 0755381b7c..ebcddfb07c 100644 --- a/doubly_linked_list/doubly_linked_list.py +++ b/doubly_linked_list/doubly_linked_list.py @@ -57,7 +57,13 @@ def add_to_head(self, value): def remove_from_head(self): if self.head is None: - return self.head.value + return None + if not self.head.next: + old_head = self.head + self.head = None + self.tail = None + self.head.delete() + return old_head.value else: removed_head = self.head self.head.delete() @@ -70,16 +76,26 @@ def add_to_tail(self, value): self.head = new_tail else: new_tail.prev = self.tail - self.tail.next = new_tail + if self.tail is not None: + self.tail.next = new_tail self.tail = new_tail def remove_from_tail(self): - old_tail = self.tail - self.tail.delete() - # new_tail = self.tail.prev - # new_tail.next = None - # self.tail = new_tail - return old_tail.value + if self.tail is None: + return None + if not self.tail.prev: + old_tail = self.tail + self.head = None + self.tail = None + self.tail.delete() + return old_tail.value + else: + old_tail = self.tail + self.tail.delete() + new_tail = self.tail.prev + # new_tail.next = None + self.tail = new_tail + return old_tail.value def move_to_front(self, node): node.delete() @@ -90,10 +106,36 @@ def move_to_end(self, node): self.add_to_tail(node.value) def delete(self, node): - new_next = node.next - new_prev = node.prev - new_prev.next = new_next - new_next.prev = new_prev + print(f'head: {self.head} node: {node}') + if node.next is None and node.prev is not None: + print('it tail') + node.prev.next = None + self.tail = node.prev + node.delete() + return node.value + if node.prev is None and node.next is not None: + print('it head') + node.next.prev = None + self.head = node.next + node.delete() + return node.value + if node.prev is None and node.next is None: + print('it both') + self.head = None + self.tail = None + node.delete() + return node.value + else: + node.prev.next = node.next + node.next.prev = node.prev + node.delete() + # if node == self.head: + # print('it head') + # self.head = node.next + # if node == self.tail: + # print('it tail') + # self.tail = node.prev + return node.value def get_max(self): max_value = int() From caa01e457103e457dcb11af297c9e3ad3e254264 Mon Sep 17 00:00:00 2001 From: kyranmccann Date: Wed, 27 Feb 2019 15:49:21 -0800 Subject: [PATCH 3/5] update with new tests --- doubly_linked_list/test_doubly_linked_list.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doubly_linked_list/test_doubly_linked_list.py b/doubly_linked_list/test_doubly_linked_list.py index f4f0b515f1..36e794fd3c 100644 --- a/doubly_linked_list/test_doubly_linked_list.py +++ b/doubly_linked_list/test_doubly_linked_list.py @@ -8,24 +8,40 @@ def setUp(self): self.dll = DoublyLinkedList(self.node) def test_list_remove_from_tail(self): + self.dll.remove_from_tail() + self.assertIsNone(self.dll.head) + self.assertIsNone(self.dll.tail) + self.dll.add_to_tail(33) + self.assertEqual(self.dll.head.value, 33) + self.assertEqual(self.dll.tail.value, 33) self.assertEqual(self.dll.remove_from_tail(), 33) self.dll.add_to_tail(68) self.assertEqual(self.dll.remove_from_tail(), 68) def test_list_remove_from_head(self): + self.dll.remove_from_head() + self.assertIsNone(self.dll.head) + self.assertIsNone(self.dll.tail) + self.dll.add_to_head(2) + self.assertEqual(self.dll.head.value, 2) + self.assertEqual(self.dll.tail.value, 2) self.assertEqual(self.dll.remove_from_head(), 2) self.dll.add_to_head(55) self.assertEqual(self.dll.remove_from_head(), 55) def test_list_add_to_tail(self): + self.assertEqual(self.dll.tail.value, 1) + self.dll.add_to_tail(30) + self.assertEqual(self.dll.tail.prev.value, 1) self.assertEqual(self.dll.tail.value, 30) self.dll.add_to_tail(20) + self.assertEqual(self.dll.tail.prev.value, 30) self.assertEqual(self.dll.tail.value, 20) def test_node_delete(self): @@ -85,9 +101,11 @@ def test_list_delete(self): self.dll.add_to_tail(6) self.dll.delete(self.dll.head) + print('head:', self.dll.head.value) self.assertEqual(self.dll.head.value, 1) self.assertEqual(self.dll.tail.value, 6) + print('head:', self.dll.head.value) self.dll.delete(self.dll.head) self.assertEqual(self.dll.head.value, 6) self.assertEqual(self.dll.tail.value, 6) From bbedc4feed58997f00c84c8dcd0931e8e43eaf47 Mon Sep 17 00:00:00 2001 From: kyranmccann Date: Wed, 27 Feb 2019 15:50:51 -0800 Subject: [PATCH 4/5] update tests --- doubly_linked_list/test_doubly_linked_list.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/doubly_linked_list/test_doubly_linked_list.py b/doubly_linked_list/test_doubly_linked_list.py index 36e794fd3c..1f5b274811 100644 --- a/doubly_linked_list/test_doubly_linked_list.py +++ b/doubly_linked_list/test_doubly_linked_list.py @@ -101,11 +101,9 @@ def test_list_delete(self): self.dll.add_to_tail(6) self.dll.delete(self.dll.head) - print('head:', self.dll.head.value) self.assertEqual(self.dll.head.value, 1) self.assertEqual(self.dll.tail.value, 6) - print('head:', self.dll.head.value) self.dll.delete(self.dll.head) self.assertEqual(self.dll.head.value, 6) self.assertEqual(self.dll.tail.value, 6) From 6ecad2df44b9ec72a8557bce43730594c1b62e69 Mon Sep 17 00:00:00 2001 From: kyranmccann Date: Wed, 27 Feb 2019 15:57:56 -0800 Subject: [PATCH 5/5] finish dll with all tests passing --- doubly_linked_list/doubly_linked_list.py | 106 ++++++++++------------- 1 file changed, 45 insertions(+), 61 deletions(-) diff --git a/doubly_linked_list/doubly_linked_list.py b/doubly_linked_list/doubly_linked_list.py index ebcddfb07c..5f95087398 100644 --- a/doubly_linked_list/doubly_linked_list.py +++ b/doubly_linked_list/doubly_linked_list.py @@ -49,53 +49,54 @@ def __init__(self, node=None): self.tail = node def add_to_head(self, value): - new_head = ListNode(value) - new_head.next = self.head - if self.head is not None: - self.head.prev = new_head - self.head = new_head + if self.head: + old_head = self.head + old_head.insert_before(value) + + self.head = self.head.prev + else: + self.head = ListNode(value) + self.tail = self.head def remove_from_head(self): - if self.head is None: - return None - if not self.head.next: - old_head = self.head - self.head = None - self.tail = None - self.head.delete() - return old_head.value + if self.head: + if self.head == self.tail: + head = self.head + self.head = None + self.tail = None + return head.value + else: + old_head = self.head + self.head = old_head.next + old_head.delete() + return old_head.value else: - removed_head = self.head - self.head.delete() - # self.head = self.head.next - return removed_head.value + return None def add_to_tail(self, value): - new_tail = ListNode(value) - if self.head is None: - self.head = new_tail + if self.tail: + self.tail.insert_after(value) + self.tail = self.tail.next + else: - new_tail.prev = self.tail - if self.tail is not None: - self.tail.next = new_tail - self.tail = new_tail + new_node = ListNode(value) + self.head = new_node + self.tail = new_node def remove_from_tail(self): - if self.tail is None: - return None - if not self.tail.prev: + if self.tail: + old_tail = self.tail - self.head = None - self.tail = None - self.tail.delete() + if self.tail == self.head: + self.tail = None + self.head = None + return old_tail.value + else: + self.tail = old_tail.prev + old_tail.delete() return old_tail.value else: - old_tail = self.tail - self.tail.delete() - new_tail = self.tail.prev - # new_tail.next = None - self.tail = new_tail - return old_tail.value + return None def move_to_front(self, node): node.delete() @@ -106,36 +107,19 @@ def move_to_end(self, node): self.add_to_tail(node.value) def delete(self, node): - print(f'head: {self.head} node: {node}') - if node.next is None and node.prev is not None: - print('it tail') - node.prev.next = None - self.tail = node.prev - node.delete() - return node.value - if node.prev is None and node.next is not None: - print('it head') - node.next.prev = None - self.head = node.next - node.delete() - return node.value - if node.prev is None and node.next is None: - print('it both') + if not self.head and not self.tail: + return None + if self.head == self.tail: self.head = None self.tail = None + if self.head == node: + self.head = node.next + node.delete() + if self.tail == node: + self.tail = node.prev node.delete() - return node.value else: - node.prev.next = node.next - node.next.prev = node.prev node.delete() - # if node == self.head: - # print('it head') - # self.head = node.next - # if node == self.tail: - # print('it tail') - # self.tail = node.prev - return node.value def get_max(self): max_value = int()