Linked List · 1 of 36
Write a Program to reverse the Linked List (Both Iterative and recursive)
Turn a train of cars around so the last car becomes the first, by flipping each coupling one at a time.
- Simple way
- time O(n)
room O(n) - Clever way
- time O(n)
room O(1)
The problem, simply
You get a linked list: a chain of boxes where every box holds a number and an arrow pointing to the next box. The last box points to nothing, which we call null.
Make the chain go the other way. The last box should become the first box, and every arrow should point backwards. Give back the new first box.
A story to remember it
Picture it
Five boxes in a row. Each arrow says who comes next. The last arrow points to null, which means the end.
After we are done, the same boxes stay where they are. Only the arrows change direction:
Same boxes, arrows flipped. Box 5 is now the head.
- answer
Examples
A normal chain
- In
1 -> 2 -> 3 -> 4 -> 5- Out
5 -> 4 -> 3 -> 2 -> 1
Every arrow turns around. Box 5 becomes the head.
Two boxes
- In
1 -> 2- Out
2 -> 1
Box 2 now points to box 1, and box 1 points to null.
One box
- In
7- Out
7
A single box turned around is the same box. Nothing to flip.
No boxes at all
- In
null- Out
null
An empty chain stays empty. Your code must not crash here.
Way 1: the simple way
Read every number into a stack, like stacking plates. Then take the plates off the top one by one and write the numbers back into the boxes from the start. The plate you put on last comes off first, so the numbers come back in reverse order.
- Walk the chain and push each number onto a stack.
- Walk the chain again from the head.
- For each box, pop the top number off the stack and write it into the box.
All five numbers are on the stack. 5 is on top, so it will be written into the first box.
- looking now
import java.util.ArrayDeque;
import java.util.Deque;
class ListNode {
int val;
ListNode next;
ListNode(int val) { this.val = val; }
}
class Solution {
public ListNode reverseList(ListNode head) {
Deque<Integer> stack = new ArrayDeque<>();
for (ListNode cur = head; cur != null; cur = cur.next) {
stack.push(cur.val); // put every number on the stack
}
for (ListNode cur = head; cur != null; cur = cur.next) {
cur.val = stack.pop(); // the last number comes off first
}
return head;
}
}How long it takes: we walk the chain two times, so the work grows with the number of boxes, O(n). How much extra room it needs: a stack as tall as the chain, O(n). It works, but it copies every number and it changes the values instead of the arrows, which some interviewers do not allow.
Way 2: the clever way
Do what you did with the train. Keep three fingers on the chain:
previs the part you already turned around. At the start it isnull.curris the box you are fixing right now.nextis where you hold on to the rest of the chain so it does not get lost.
For each box: save next, flip the arrow of curr to point at prev, then slide prev and curr one step forward. When curr falls off the end, prev is the new head.
Flip the arrows one box at a time
01 / 11
Start. Nothing is turned around yet, so prev is null. curr is at the first box.
- looking now
- done
- answer
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null; // the part that is already turned around
ListNode curr = head; // the box we are fixing now
while (curr != null) {
ListNode next = curr.next; // hold on to the rest of the chain
curr.next = prev; // flip the arrow
prev = curr; // slide prev forward
curr = next; // slide curr forward
}
return prev; // prev is the new head
}
}How long it takes: we touch each box once, O(n). How much extra room it needs: just three fingers, no matter how long the chain is, O(1).
Another way: recursion
You can also ask a helper to turn around everything after the first box, then fix the first box yourself. The helper asks another helper, and so on, until a helper gets a chain of one box, which is already turned around.
Helpers turn the tail around, then each one fixes its own box
01 / 05
reverse(1) asks a helper to reverse the chain that starts at box 2.
- looking now
- done
- answer
class Solution {
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null) return head; // zero or one box
ListNode newHead = reverseList(head.next); // helper turns the tail around
head.next.next = head; // the box after me points back to me
head.next = null; // I am the end now
return newHead;
}
}This also takes O(n) time, but every waiting helper sits on the call stack, so it needs O(n) extra room. A chain of a million boxes can overflow the stack.
Watch out for
- Returning
headat the end. After the flip,headis the last box. Returnprev. - Forgetting the empty list and the one box list. The loop handles both if
prevstarts atnull. - In the recursive way, forgetting
head.next = nullleaves a loop between the first two boxes.
What interviewers ask next
- Reverse only the boxes from position
mton. Walk to boxm - 1, reversen - m + 1boxes with the same three fingers, then stitch both ends back. - Reverse in groups of
k. Reverse one group, then let the group's old first box point to the result of the next group. - Can you do it faster than
O(n)? No. Every arrow must change, and there arenarrows. - Check if a list is a palindrome. Reverse the second half, then compare it with the first half.
Remember this
Grown-up words: the boxes are nodes, the arrows are next pointers, the three fingers are the three pointer technique, and the helpers waiting on each other are the recursion call stack.