|
| 1 | +''' |
| 2 | +Find the middle element of a linked list |
| 3 | +
|
| 4 | +Our challenge is to now find the middle node in a linked list. |
| 5 | +We don't initially know the length of a linked list, all we have is a single node which acts as the head of the linked list and which we can access all other nodes by traversing through each nodes "next" property. |
| 6 | +We can continuously loop through each node until we get to a node that has a "next" property of null, which means we have reached the last node. |
| 7 | +
|
| 8 | +https://coderbyte.com/algorithm/linked-list-middle-element |
| 9 | +''' |
| 10 | + |
| 11 | + |
| 12 | +class Node: |
| 13 | + def __init__(self, data): |
| 14 | + self.data = data |
| 15 | + self.next = None |
| 16 | + |
| 17 | + |
| 18 | +class LinkedList: |
| 19 | + def __init__(self): |
| 20 | + self.root = None |
| 21 | + |
| 22 | + def insert_at_end(self, data): |
| 23 | + new_node = Node(data) |
| 24 | + |
| 25 | + if self.root is None: |
| 26 | + self.root = new_node |
| 27 | + else: |
| 28 | + current = self.root |
| 29 | + while current.next is not None: |
| 30 | + current = current.next |
| 31 | + current.next = new_node |
| 32 | + |
| 33 | + def print_list(self): |
| 34 | + print('List:') |
| 35 | + current = self.root |
| 36 | + while current is not None: |
| 37 | + print(current.data, '-> ', end='') |
| 38 | + current = current.next |
| 39 | + |
| 40 | + ''' |
| 41 | + Traverse all the list nodes and count how many elements there are in total. |
| 42 | + Then traverse it again this time stopping at the total/2 node. |
| 43 | + ''' |
| 44 | + def get_middle_element_1(self): |
| 45 | + current = self.root |
| 46 | + length = 0 |
| 47 | + |
| 48 | + # walk until the end of the list to find it's length |
| 49 | + while current is not None: |
| 50 | + length += 1 |
| 51 | + current = current.next |
| 52 | + |
| 53 | + current = self.root |
| 54 | + # walk until the middle of the list length |
| 55 | + for i in range(1, length//2): |
| 56 | + current = current.next |
| 57 | + |
| 58 | + return current.data |
| 59 | + |
| 60 | + ''' |
| 61 | + Traverse the list using two pointers: |
| 62 | + one that will traverse the linked list one node at a time, |
| 63 | + and the other pointer will traverse two nodes at a time. |
| 64 | + This way when the faster pointer reaches the end of the linked list, |
| 65 | + the slower pointer will be halfway there. |
| 66 | + ''' |
| 67 | + def get_middle_element_2(self): |
| 68 | + fastPointer = self.root.next |
| 69 | + slowPointer = self.root |
| 70 | + |
| 71 | + # the fast pointer walks two nodes at a time and the slow just one |
| 72 | + while fastPointer.next is not None and fastPointer.next.next is not None: |
| 73 | + fastPointer = fastPointer.next.next |
| 74 | + slowPointer = slowPointer.next |
| 75 | + |
| 76 | + return slowPointer.data |
| 77 | + |
| 78 | + |
| 79 | +list = LinkedList() |
| 80 | + |
| 81 | +for x in range(1, 11): |
| 82 | + list.insert_at_end(x) |
| 83 | + |
| 84 | +list.print_list() |
| 85 | + |
| 86 | +print('\n\nMiddle list element:', list.get_middle_element_1()) |
| 87 | + |
| 88 | +print('\n\nMiddle list element:', list.get_middle_element_2()) |
0 commit comments