|
1 | 1 | from __future__ import annotations
|
2 | 2 |
|
3 |
| - |
4 | 3 | class Node:
|
| 4 | + """Represents a node in the linked list.""" |
5 | 5 | def __init__(self, data: int) -> None:
|
6 | 6 | self.data = data
|
7 | 7 | self.next = None
|
8 | 8 |
|
9 |
| - |
10 | 9 | class LinkedList:
|
11 |
| - def __init__(self): |
| 10 | + """Represents a linked list.""" |
| 11 | + def __init__(self) -> None: |
12 | 12 | self.head = None
|
| 13 | + self.size = 0 # Keep track of the list size |
13 | 14 |
|
14 |
| - def push(self, new_data: int) -> int: |
| 15 | + def push(self, new_data: int) -> None: |
| 16 | + """Adds a new node to the front of the list.""" |
15 | 17 | new_node = Node(new_data)
|
16 | 18 | new_node.next = self.head
|
17 | 19 | self.head = new_node
|
18 |
| - return self.head.data |
| 20 | + self.size += 1 # Increment the list size |
19 | 21 |
|
20 | 22 | def middle_element(self) -> int | None:
|
21 |
| - """ |
22 |
| - >>> link = LinkedList() |
23 |
| - >>> link.middle_element() |
24 |
| - No element found. |
25 |
| - >>> link.push(5) |
26 |
| - 5 |
27 |
| - >>> link.push(6) |
28 |
| - 6 |
29 |
| - >>> link.push(8) |
30 |
| - 8 |
31 |
| - >>> link.push(8) |
32 |
| - 8 |
33 |
| - >>> link.push(10) |
34 |
| - 10 |
35 |
| - >>> link.push(12) |
36 |
| - 12 |
37 |
| - >>> link.push(17) |
38 |
| - 17 |
39 |
| - >>> link.push(7) |
40 |
| - 7 |
41 |
| - >>> link.push(3) |
42 |
| - 3 |
43 |
| - >>> link.push(20) |
44 |
| - 20 |
45 |
| - >>> link.push(-20) |
46 |
| - -20 |
47 |
| - >>> link.middle_element() |
48 |
| - 12 |
49 |
| - >>> |
50 |
| - """ |
51 |
| - slow_pointer = self.head |
52 |
| - fast_pointer = self.head |
53 |
| - if self.head: |
54 |
| - while fast_pointer and fast_pointer.next: |
55 |
| - fast_pointer = fast_pointer.next.next |
56 |
| - slow_pointer = slow_pointer.next |
57 |
| - return slow_pointer.data |
58 |
| - else: |
| 23 | + """Returns the middle element of the list.""" |
| 24 | + if not self.head: |
59 | 25 | print("No element found.")
|
60 | 26 | return None
|
61 | 27 |
|
| 28 | + slow_pointer = self.head |
| 29 | + fast_pointer = self.head |
| 30 | + while fast_pointer and fast_pointer.next: |
| 31 | + fast_pointer = fast_pointer.next.next |
| 32 | + slow_pointer = slow_pointer.next |
| 33 | + return slow_pointer.data |
| 34 | + |
| 35 | + def __str__(self) -> str: |
| 36 | + """Returns a string representation of the list.""" |
| 37 | + nodes = [] |
| 38 | + current = self.head |
| 39 | + while current: |
| 40 | + nodes.append(str(current.data)) |
| 41 | + current = current.next |
| 42 | + return ' -> '.join(nodes) |
| 43 | + |
| 44 | +def find_middle_element(linked_list: LinkedList) -> int | None: |
| 45 | + """ |
| 46 | + Algorithm: Find the Middle Element of a Linked List |
| 47 | +
|
| 48 | + This algorithm uses the slow and fast pointer technique to find the middle element of a linked list. |
| 49 | +
|
| 50 | + Time Complexity: O(n/2) = O(n) |
| 51 | + Space Complexity: O(1) |
| 52 | +
|
| 53 | + :param linked_list: The linked list to find the middle element of |
| 54 | + :return: The middle element of the linked list, or None if the list is empty |
| 55 | + """ |
| 56 | + if not linked_list.head: |
| 57 | + print("No element found.") |
| 58 | + return None |
| 59 | + |
| 60 | + slow_pointer = linked_list.head |
| 61 | + fast_pointer = linked_list.head |
| 62 | + while fast_pointer and fast_pointer.next: |
| 63 | + fast_pointer = fast_pointer.next.next |
| 64 | + slow_pointer = slow_pointer.next |
| 65 | + return slow_pointer.data |
62 | 66 |
|
63 | 67 | if __name__ == "__main__":
|
64 | 68 | link = LinkedList()
|
65 |
| - for _ in range(int(input().strip())): |
66 |
| - data = int(input().strip()) |
| 69 | + num_elements = int(input("Enter the number of elements: ")) |
| 70 | + for _ in range(num_elements): |
| 71 | + data = int(input("Enter element {}: ".format(_ + 1))) |
67 | 72 | link.push(data)
|
68 |
| - print(link.middle_element()) |
| 73 | + print("Linked List:", link) |
| 74 | + print("Middle Element:", find_middle_element(link)) |
0 commit comments