You are given the head of a singly linked list, a 1-based position pos, and a value val. Insert a new node holding val at position pos and return the head of the modified list.
After the insertion, the new node occupies the pos-th slot (counting from 1). Everything that was at position pos and beyond simply slides one step to the right; everything before it stays exactly where it was.
Two boundaries are worth naming:
pos = 1 means the new value becomes the new head.pos = size + 1 means the new value is appended just past the current last node.Input: head = [1, 3], pos = 3, val = 4 Output: 1 -> 3 -> 4 Position 3 is one past the last node, so 4 is appended to the end.
Input: head = [1, 2, 9], pos = 2, val = 5 Output: 1 -> 5 -> 2 -> 9 5 is inserted before the node at position 2, landing between 1 and 2.
- 1 <= list size <= 10^4 - 1 <= pos <= list size + 1 - 1 <= val <= 10^4
Inserting at an arbitrary position is where linked lists start to feel powerful: no shifting a million elements like an array would. You reach the one spot that matters, rewire two pointers, and you're done — the rest of the list never moves.
next pointer to the following node; the last node's next is null.head so that inserting at position 1 needs no special case.In plain terms: find the node at position pos - 1 (the predecessor), make the new node point to whatever the predecessor pointed to, then make the predecessor point to the new node.
Worked example — head = [1, 3], pos = 3, val = 4
before: head → [1] → [3] → null pos = 3, val = 4 walk to the node before position 3 → that's [3] (the 2nd node) create: new [4], set [4].next = [3].next (null) relink: [3].next = [4] after: head → [1] → [3] → [4] → null answer: 1 -> 3 -> 4
Naming the boundaries out loud — position 1, position size+1 — before touching a pointer is exactly what an interviewer wants to hear.
“Is pos 1-based or 0-based?”
It changes every index in your loop; here it is 1-based, so position 1 is the head.
“Can pos be 1, and can it be size + 1?”
Yes to both — position 1 replaces the head, and size+1 appends at the very end; a good solution handles both without extra branches.
“How large can the list get?”
Up to 10^4 nodes, so a single walk to the position is fine, but copying the whole list into an array is needless extra memory.
Let me confirm a couple of things before I code.
Position is 1-based, so pos equal to 1 means the new node becomes the head — correct?
And pos equal to size plus one means I append at the end, which I'll cover with a sentinel node so there's no special case.
Insertion happens after the node at position pos - 1. That predecessor is the only node you need a handle on — everything downstream is reached through its next pointer.
prev = node at position pos-1 new.next = prev.next # new points at the rest prev.next = new # prev points at new
Position 1 has no predecessor inside the list — the predecessor is the head slot. Place a sentinel dummy before head; now position 1's predecessor is dummy, and one loop handles every position uniformly. Return dummy.next at the end.
Set new.next = prev.next before prev.next = new. Reverse them and prev.next already points at new, so new.next = prev.next makes the node point at itself and the tail is lost.
| Copy to array | One-pass splice | |
|---|---|---|
| Idea | Dump values into an array, insert, rebuild the list | Walk to pos-1, rewire two pointers |
| Time | O(n) | O(n) |
| Space | O(n) | O(1) |
| Passes | Two (copy + rebuild) | One (partial walk) |
Both are linear in time, but the array copy duplicates data that already lives in memory. The optimal move reaches the spot once and rewires in place — full code is in the Approaches selector below.
Key takeaway
To insert at position pos, walk a sentinel-anchored pointer pos - 1 steps to reach the predecessor, then splice: new.next = prev.next, prev.next = new. The dummy node makes position 1 ordinary, and the two-line rewire keeps it O(1) extra space.
dummy = Node(0); dummy.next = head prev = dummy repeat pos-1 times (or until prev.next is null): prev = prev.next prev.next = Node(val, prev.next) return dummy.next