Opening the reading…
Opening the reading…
LINKED LIST › LINKED LIST (PART 1)
Open — the attempt gate is not wired up yet
This editorial is meant to unlock after you have run the problem at least once, with the worked solution behind one further deliberate click. That needs per-learner unlock state nothing stores today, so for now the whole article is open.
Try it yourself first →A singly linked list gives you only one direction to follow: from a node to its next node. Reversing the list means changing every link so it points to the node you just came from. While you change one link, you must still remember the original next node, because after the change the original forward path is no longer reachable from the current node.
Keep prev as the already reversed part and curr as the first node not yet processed. Save curr->next, point curr back to prev, then move both pointers forward. When curr becomes null, every link has been reversed and prev points to the new head. The original head has become the final node, so its next pointer is already null.
| MEASURE | BOUND | WHY |
|---|---|---|
| Time | O(n) | Each node becomes curr once, and each iteration performs a constant number of pointer reads and writes. The loop advances curr to the next unprocessed node, so no node is processed twice. |
| Space | O(1) extra space | The algorithm stores only prev, curr, and next; the reversed list is required output and is excluded from the working-memory bound. The bound remains constant even for the worst-shaped input, a list containing all n nodes in one chain. |
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr != nullptr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};The order of the four statements inside the loop is the solution's invariant made executable. The assignment to next must happen before curr->next changes; after that change, curr no longer points forward. The return value is prev rather than head because the original head moves to the tail, while the original tail becomes the new entry point.
Recursion can reverse the suffix first, then attach the current node after the suffix's original tail. For a node head, reverseList(head->next) returns the new head of the reversed suffix. The old second node is now at that suffix's tail, so setting head->next->next to head puts head after it, and setting head->next to null prevents a cycle.
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == nullptr || head->next == nullptr) {
return head;
}
ListNode* newHead = reverseList(head->next);
head->next->next = head;
head->next = nullptr;
return newHead;
}
};