Delete Node in a Linked List
You are given only the node to delete (never the tail), with no access to the head. Delete it.
Open on LeetCode ↗Intuition
You cannot reach the previous node to rewire it. So delete by impersonation: copy the next node's value into this node, then unlink the next node. From outside, the target value has vanished.
A puzzle about reframing: you're given only the node to delete, with no access to its predecessor, so you cannot unlink it in the usual way. The move is to stop thinking about deleting this node and instead overwrite it with its successor's data, then unlink the successor. The node object survives; the value disappears, which is all anyone can observe.
Approach
The usual deletion is impossible here
Normally you delete a node by finding its predecessor and rerouting prev.next past it. But this problem hands you only the node itself — no head, no way to walk to the predecessor. So the standard technique simply can't run, and we need a different mental model of what 'delete' means.
Delete by impersonation, not removal
If you can't remove this node, make it become the next node instead. Copy the successor's value into this node (node.val = node.next.val), then bypass the successor (node.next = node.next.next). After that, this node carries the value that used to be next, and the original next node is unreachable. From the outside, the value you were asked to delete has vanished and the list reads identically.
Two writes, and why the guarantee matters
It's literally two pointer assignments. The whole trick depends on node.next existing — which is exactly why the problem promises the given node is never the tail. If it were the tail there'd be no successor to copy from, and the technique would fail. O(1) time, O(1) space.
Solution & live demo
Common pitfalls
Trying to unlink the node itself
node.prev.next = node.next
node.val = node.next.val node.next = node.next.next
It's a singly linked list and you were handed no head pointer, so the predecessor is unreachable. Impersonating the next node achieves the same observable result without it.
Copying the value but not relinking
node.val = node.next.val
node.val = node.next.val node.next = node.next.next
The value now appears twice in a row and the list keeps its original length. Both steps are needed: take over the successor's identity, then remove the successor.
Assuming it works for the tail
# called on the last node
# guaranteed by the problem: node is never the tail
There is no successor to impersonate, and node.next.val raises. The technique fundamentally cannot delete a tail node — which is why the constraints rule that case out.
Edge cases
Its successor's value is copied in and the successor is skipped — the list reads identically minus the target value.
Relies on node.next existing; the problem promises the node is not last, so this is safe.
Only the given node is altered; other nodes with the same value are untouched.