Linked List
Reverse a singly linked list and return the new head.
Walk the list once, and at each node, flip its `next` pointer to point backward instead of forward — but save the original `next` first, or you'll lose the rest of the list. Track the previous node as you go; by the end, what used to be the last node is now the head. A recursive version does the same rewiring, just using the call stack to hold position instead of a loop variable.
// Reverse a singly linked list and return the new head.
class ListNode {
constructor(value, next = null) {
this.value = value;
this.next = next;
}
}
function buildList(values) {
const head = new ListNode(values[0]);
let current = head;
for (let i = 1; i < values.length; i++) {
current.next = new ListNode(values[i]);
current = current.next;
}
return head;
}
function toArray(head) {
const out = [];
let current = head;
while (current) {
out.push(current.value);
current = current.next;
}
return out;
}
// --- Iterative: rewire one pointer at a time, O(1) extra space ---
function reverseListIterative(head) {
let prev = null;
let current = head;
while (current) {
const next = current.next; // save before we overwrite it
current.next = prev; // flip the pointer backward
prev = current;
current = next;
}
return prev; // prev is the new head
}
// --- Recursive: same idea, but the call stack tracks position instead
// of a loop variable. Uses O(n) space for the recursion. ---
function reverseListRecursive(head) {
if (head === null || head.next === null) return head;
const newHead = reverseListRecursive(head.next);
head.next.next = head; // make the next node point back to this one
head.next = null;
return newHead;
}
// --- Example Usage ---
const list = buildList([1, 2, 3, 4, 5]);
console.log("original:", toArray(list)); // [1,2,3,4,5]
console.log("reversed (iterative):", toArray(reverseListIterative(buildList([1, 2, 3, 4, 5])))); // [5,4,3,2,1]
console.log("reversed (recursive):", toArray(reverseListRecursive(buildList([1, 2, 3, 4, 5])))); // [5,4,3,2,1]