You're given the head of a singly linked list — a chain of nodes where each node knows only the one after it — and a number n. Remove the node that sits n positions from the end of the list (the last node is n = 1), then return the head of the list that remains. The catch that makes this interesting: a singly linked list has no way to walk backwards, so "count from the end" is not something you can do directly. The classic solution finds the node in a single pass using two pointers spaced n nodes apart.
// A node is a plain object: { val, next }.
// - val: any value carried by the node.
// - next: the next node, or null at the end of the list.
// The list is identified by its head node; an empty list is `null`.
//
// n is 1-indexed FROM THE END: n = 1 is the last node, n = length is the head.
function linkedListDeleteNthFromEnd(head, n): Node | null;
A list like 1 -> 2 -> 3 is built as nested objects:
const head = { val: 1, next: { val: 2, next: { val: 3, next: null } } };
// Delete the 2nd node from the end of 1 -> 2 -> 3 -> 4 -> 5.
// Counting from the end: 5 is 1st, 4 is 2nd. Remove the 4.
linkedListDeleteNthFromEnd(buildList([1, 2, 3, 4, 5]), 2);
// → 1 -> 2 -> 3 -> 5
// When n equals the length, the target IS the head — return the new head.
linkedListDeleteNthFromEnd(buildList([1, 2, 3]), 3);
// → 2 -> 3
// A single node removed leaves an empty list.
linkedListDeleteNthFromEnd(buildList([42]), 1);
// → null
n is 1-indexed from the end. n = 1 removes the last node; n = length removes the head. There is no n = 0.n is always valid. You can assume 1 <= n <= length. You don't need to guard against n larger than the list or a null head with n > 0.n === length, the node to delete is the head itself, so the function must be able to return a different head than it was given.null, not a node.next, you do not construct a fresh list.