Reversing a Linked List: the sane way, the recursive way and the push way
Reversing a SLL takes O(N)
. You can reverse a doubly linked list in O(1)
if you swap head
and tail
and you’re ok with going backwards with next
and vice versa.
The sane and obvious way is to use three pointers (back
, middle
and front
); you make the middle
point to back
, and shift everything one step right until front
is None
.
def bmfReverse(self): back = None middle = self.head front = middle.next while True: middle.next = back if front is None: break # advance the three pointers back = middle middle = front front = front.next self.head = middle
It is easy to turn this into a recursive function.
def recBmf(self, back=None, middle=None, front=None): # setup if middle is None: middle = self.head if front is None: front = middle.next middle.next = back # base case if front is None: self.head = middle return return self.recBmf(middle, front, front.next)
Finally, that’s the push-reverse strategy. It’s fucked up weird to read, but the idea is actually pretty simple: you keep pushing the front node (current
) on the new result
list, and as a last step you update the head pointer. Source: http://cslibrary.stanford.edu/105/LinkedListProblems.pdf
def pushReverse(self): result = None current = self.head while current is not None: # save the next node next = current.next # move the node onto result current.next = result result = current # update current current = next self.head = result
Bonus: reversing a doubly linked list
Oh Python, it’s not even fun this way!
def reverse(self): n = self.head while n is not None: n.next, n.prev = n.prev, n.next n = n.prev self.head, self.tail = self.tail, self.head