LC 206 - Reverse Linked List
Question
Given the head of a singly linked list, reverse the list, and return the reversed list.
Example 1:
1
2
Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]
Example 2:
1
2
Input: head = [1,2]
Output: [2,1]
Example 3:
1
2
Input: head = []
Output: []
Constraints:
- The number of nodes in the list is the range
[0, 5000]. -5000 <= Node.val <= 5000
Follow up: A linked list can be reversed either iteratively or recursively. Could you implement both?
Links
Question here and solution here
Solution
concept
iterative
recursive
For NeetCode solution: if the example linked list is [1, 2, 3, 4, 5] In the recursive call, the deepest layer returns head = ListNode{val: 5, next: None} or [5] From the next layer up of the recursive call, head is now ListNode{val: 4, next: ListNode{val: 5, next: None}} or [4, 5], and newHead = ListNode{val: 5, next: None} or [5], as it is returned from the deepest call. The [5]s in both head and newHead are the SAME listnode. Now, head.next.next = head, so your head should be [4, 5, 4, 5, 4, 5, 4, 5... (its cyclical)], and newhead should be [5, 4, 5, 4, 5, 4...] since the [5] and [4] list nodes are the same between head and newHead. Then call head.next = null so head should be effectively truncated to [4], since head.next is the node after [4] to be removed. newHead is truncated to [5, 4], since anything after the first [4] is removed. From the next level up the recursion call, head is [3, 4] since the listNode [5] was removed from head. head.next.next = head changes head to [3, 4, 3, 4, 3...]. And newHead is [5, 4, 3, 4, 3, 4, 3...]. Then head.next = null truncates head to [3]. Repeat until the list is reversed. Head.next = null effectively stops the linkedList from referencing itself forever.
Alternatively, we can think of the solution as:
- at each recursive call, we first store the current
headtohewHead, thisnewHeadwill change from1 -> .. -> 5when reached the deepest layer and remains at5and gets returned all the way up. head.next.next = headessentially create a loop between4and5, and thenhead.next = Nonecut free4 -> 5and whats left is5 - > 4.- As the recursive returns up, the
headwill change from4to3, and then create loop between3and4withhead.next.next = headand then break3 - > 4withhead.next = None.
code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
"""
iterative
"""
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev, cur = None, head
while cur is not None:
next_node = cur.next
cur.next = prev
prev = cur
cur = next_node
return prev
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def helper(prev, cur):
if cur is None:
return prev
next_node = cur.next
cur.next = prev
new_head = helper(cur, next_node)
return new_head
return helper(None, head)
class NeetSolution:
"""
recursive
"""
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head:
return None
newHead = head
if head.next:
newHead = self.reverseList(head.next)
head.next.next = head # head will reach 5 and then when it returns, it will be at 4, 3, 2, 1.
head.next = None
return newHead # newHead will reach 5 and remains 5 and gets returned all the way up
Complexity
time: $O(n)$
space: $O(1)$ if iterative solution, $O(n)$ if recursive solution.

