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? diff --git a/doubly_linked_list/doubly_linked_list.py b/doubly_linked_list/doubly_linked_list.py index 0755381b7c..5f95087398 100644 --- a/doubly_linked_list/doubly_linked_list.py +++ b/doubly_linked_list/doubly_linked_list.py @@ -49,37 +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 self.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 - 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): - 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: + + old_tail = self.tail + 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: + return None def move_to_front(self, node): node.delete() @@ -90,10 +107,19 @@ 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 + 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() + else: + node.delete() def get_max(self): max_value = int() diff --git a/doubly_linked_list/test_doubly_linked_list.py b/doubly_linked_list/test_doubly_linked_list.py index f4f0b515f1..1f5b274811 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):