|
| 1 | + |
| 2 | +# Reverse Linked List |
| 3 | +Given the head of a singly linked list, reverse the list and return the reversed list. |
| 4 | + |
| 5 | +### Constraints: |
| 6 | +- The number of nodes in the list is the range [0, 5000]. |
| 7 | +- -5000 <= Node.val <= 5000 |
| 8 | + |
| 9 | +### Examples |
| 10 | +```javascript |
| 11 | +Input: head = [1,2,3,4,5] |
| 12 | +Output: [5,4,3,2,1] |
| 13 | + |
| 14 | +Input: head = [1,2] |
| 15 | +Output: [2,1] |
| 16 | + |
| 17 | +Input: head = [] |
| 18 | +Output: [] |
| 19 | +``` |
| 20 | + |
| 21 | +### Follow-up: |
| 22 | +A linked list can be reversed either iteratively or recursively. Could you implement both? |
| 23 | + |
| 24 | +## Approaches to Solve the Problem |
| 25 | +### Approach 1: Iterative Solution (Optimal) |
| 26 | +##### Intuition: |
| 27 | +In the iterative approach, the goal is to reverse the direction of the links between the nodes. We can achieve this by maintaining three pointers: prev, curr, and next. We iterate through the list, reversing the next pointer of each node until we reach the end of the list. |
| 28 | + |
| 29 | +- prev: Keeps track of the previous node (initially None because the new tail will point to None). |
| 30 | +- curr: Points to the current node being processed. |
| 31 | +- next: Points to the next node in the original list so that we can continue processing after modifying the current node’s next pointer. |
| 32 | + |
| 33 | +Steps: |
| 34 | +1. Initialize three pointers: prev = None, curr = head, and next = None. |
| 35 | +2. While curr is not None, repeat the following steps: |
| 36 | + - Store curr.next in next to keep track of the remaining list. |
| 37 | + - Set curr.next to prev to reverse the link. |
| 38 | + - Move prev to curr and curr to next. |
| 39 | +3. After the loop, prev will point to the new head of the reversed list. |
| 40 | +4. Return prev. |
| 41 | +##### Visualization: |
| 42 | +For head = [1, 2, 3, 4, 5]: |
| 43 | +```rust |
| 44 | +Initial: |
| 45 | +prev = None, curr = 1, next = None |
| 46 | + |
| 47 | +Iteration 1: |
| 48 | +next = 2 |
| 49 | +Reverse 1's next to None → prev = 1, curr = 2 |
| 50 | + |
| 51 | +Iteration 2: |
| 52 | +next = 3 |
| 53 | +Reverse 2's next to 1 → prev = 2, curr = 3 |
| 54 | + |
| 55 | +... |
| 56 | + |
| 57 | +Final: |
| 58 | +prev = 5 (new head), curr = None |
| 59 | +Reversed list: [5, 4, 3, 2, 1] |
| 60 | +``` |
| 61 | +##### Time Complexity: |
| 62 | +O(n), where n is the number of nodes in the list. We traverse the list once. |
| 63 | +##### Space Complexity: |
| 64 | +O(1), as we only use a few pointers to reverse the list in place. |
| 65 | +##### Python Code: |
| 66 | +```python |
| 67 | +class ListNode: |
| 68 | + def __init__(self, val=0, next=None): |
| 69 | + self.val = val |
| 70 | + self.next = next |
| 71 | + |
| 72 | +def reverseList(head: ListNode) -> ListNode: |
| 73 | + prev = None |
| 74 | + curr = head |
| 75 | + |
| 76 | + while curr: |
| 77 | + next_node = curr.next # Store the next node |
| 78 | + curr.next = prev # Reverse the current node's pointer |
| 79 | + prev = curr # Move prev to current node |
| 80 | + curr = next_node # Move to the next node |
| 81 | + |
| 82 | + return prev # prev will be the new head after the loop |
| 83 | +``` |
| 84 | +### Approach 2: Recursive Solution |
| 85 | +##### Intuition: |
| 86 | +The recursive approach works by breaking the problem into smaller subproblems. The idea is to reverse the rest of the list first and then make the current node point to its previous node. This approach implicitly uses the call stack to keep track of the nodes as we recursively process them. |
| 87 | + |
| 88 | +Steps: |
| 89 | +1. If the head is None or head.next is None, return head (base case: the list is empty or has one node). |
| 90 | +2. Recursively reverse the rest of the list: rest = reverseList(head.next). |
| 91 | +3. After reversing the rest, set head.next.next = head to make the next node point back to the current node. |
| 92 | +4. Set head.next = None to avoid a cycle in the reversed list. |
| 93 | +5. Return the rest, which is the new head of the reversed list. |
| 94 | + |
| 95 | +##### Visualization: |
| 96 | +For head = [1, 2, 3, 4, 5]: |
| 97 | + |
| 98 | +```perl |
| 99 | +Recursive call: reverseList([2, 3, 4, 5]) |
| 100 | +Recursive call: reverseList([3, 4, 5]) |
| 101 | +... |
| 102 | + |
| 103 | +Base case: |
| 104 | +reverseList([5]) → return [5] |
| 105 | + |
| 106 | +Backtrack: |
| 107 | +4.next.next = 4 → list becomes [5, 4] |
| 108 | +3.next.next = 3 → list becomes [5, 4, 3] |
| 109 | +... |
| 110 | +``` |
| 111 | +##### Time Complexity: |
| 112 | +O(n), where n is the number of nodes in the list. We traverse the list once. |
| 113 | +##### Space Complexity: |
| 114 | +O(n), because of the recursive call stack that grows to a depth of n. |
| 115 | +##### Python Code: |
| 116 | +```python |
| 117 | +class ListNode: |
| 118 | + def __init__(self, val=0, next=None): |
| 119 | + self.val = val |
| 120 | + self.next = next |
| 121 | + |
| 122 | +def reverseList(head: ListNode) -> ListNode: |
| 123 | + # Base case: if the list is empty or has only one node, return head |
| 124 | + if not head or not head.next: |
| 125 | + return head |
| 126 | + |
| 127 | + # Recursively reverse the rest of the list |
| 128 | + rest = reverseList(head.next) |
| 129 | + |
| 130 | + # Make the next node point back to the current node |
| 131 | + head.next.next = head |
| 132 | + # Set the current node's next to None (it becomes the new tail) |
| 133 | + head.next = None |
| 134 | + |
| 135 | + # Return the new head (the result of reversing the rest) |
| 136 | + return rest |
| 137 | +``` |
| 138 | +## Summary |
| 139 | + |
| 140 | +| Approach | Time Complexity | Space Complexity | |
| 141 | +|-----------------------------------|-----------------|------------------| |
| 142 | +| Iterative | O(n) | O(1) | |
| 143 | +| Recursive | O(n) | O(n) | |
| 144 | + |
| 145 | +Both the iterative and recursive solutions have the same time complexity, but the iterative solution is more space-efficient since it doesn't use the call stack. |
0 commit comments