We need to rearrange a singly linked list so that nodes alternate between the front and the back. Take the first node, then the last node, then the second node, then the second-to-last node, and so on. The difficulty is that this is a singly linked list, so we cannot traverse backward to reach those "back" nodes cheaply.
The reordered list is the first half of the original interleaved with its second half reversed. For [1, 2, 3, 4, 5], that means interleaving the first half [1, 2, 3] with the reversed second half [5, 4] to get 1 -> 5 -> 2 -> 4 -> 3. Every approach below relies on this structure. They differ only in how they reach the back nodes: by copying references into an array, or by reversing the second half in place.
5 * 10^4 nodes. An O(n^2) approach, such as repeatedly scanning to the tail to find the last unplaced node, would run up to 2.5 billion operations and time out. An O(n) solution is required.1 <= Node.val <= 1000) and must not be modified. We rearrange the nodes themselves, never their values, so the value range does not affect the approach.The difficulty with a singly linked list is the lack of backward movement. Storing every node reference in an array removes that restriction: an array gives O(1) access to any position, including the last. With all nodes in an array, two pointers, one at the front and one at the back, can rewire the next connections directly in the required interleaved order.
This spends O(n) extra space to avoid any pointer reversal. It is the more direct of the two approaches and a useful baseline before the in-place version.
left = 0 and right = n - 1 (where n is the number of nodes).left < right:nodes[left].next = nodes[right] (connect front node to back node).left by 1.left == right, break (we've met in the middle).nodes[right].next = nodes[left] (connect back node to the next front node).right by 1.next to null to terminate the list.Loading animation...
The array stores every node, so this uses O(n) extra space. The next approach reaches the back nodes by reversing the second half in place, which removes the array and drops the space to O(1).
The reordered list is the first half interleaved with the reversed second half, and all three pieces can be done in place with constant extra space:
Finding the middle uses two pointers at different speeds: slow moves one node per step, fast moves two. When fast can no longer advance two nodes, slow sits at the end of the first half. We then reverse everything after slow and alternate nodes from the two halves.
The way slow/fast advance leaves the first half with ceil(n/2) nodes and the reversed second half with floor(n/2) nodes, so the first half is always the same length as the second or exactly one node longer. The merge loop pulls one node from each half per iteration and stops when the second half is exhausted. Because the first half is never shorter, the leftover first-half node (present only when n is odd) is already the last node and keeps its original next, which the disconnection step set to null. No node is dropped or visited twice.
slow points to the end of the first half.slow.next. Use the standard iterative reversal (prev/curr/next pointers).slow.next = null.Loading animation...