Most linked-list problems use a few techniques: rewiring the next pointers, two pointers (slow/fast or with a gap) and a dummy head. The Node class is familiar from the linked lists topic: Node(value, next).
Helper functions
For tests it is handy to build a list from an array and convert it back.
class Node:
def __init__(self, value, next=None):
self.value = value
self.next = next
def build(items):
head = None
for v in reversed(items):
head = Node(v, head)
return head
def to_list(head):
out = []
while head:
out.append(head.value)
head = head.next
return out
print(to_list(build([1, 2, 3])))[1, 2, 3]Reversing a list
Keep three pointers: prev (the head of the already reversed part), head (the current node) and nxt (the next node that must not be lost). On every step point head.next at prev. Time O(n), memory O(1).
def reverse(head):
prev = None
while head:
nxt = head.next
head.next = prev
prev = head
head = nxt
return prev
print(to_list(reverse(build([1, 2, 3, 4]))))
print(to_list(reverse(None)))[4, 3, 2, 1]
[]💡 Write
nxt = head.nextbeforehead.next = prev, otherwise the rest of the list is lost.