{x}
blog image

Reorder List

You are given the head of a singly linked-list. The list can be represented as:

L0 → L1 → … → Ln - 1 → Ln

Reorder the list to be on the following form:

L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …

You may not modify the values in the list's nodes. Only nodes themselves may be changed.

 

Example 1:

Input: head = [1,2,3,4]
Output: [1,4,2,3]

Example 2:

Input: head = [1,2,3,4,5]
Output: [1,5,2,4,3]

 

Constraints:

  • The number of nodes in the list is in the range [1, 5 * 104].
  • 1 <= Node.val <= 1000

Solution Explanation: Reorder List

This problem asks us to reorder a singly linked list in a specific pattern. The approach uses three main steps:

  1. Find the Middle: We use two pointers, slow and fast, to find the middle of the linked list. The slow pointer moves one step at a time, while the fast pointer moves two steps at a time. When the fast pointer reaches the end (or null), the slow pointer will be at (or near) the middle.

  2. Reverse the Second Half: We reverse the second half of the linked list (from slow.next onwards). This is a standard linked list reversal technique. We iterate through the second half, changing each node's next pointer to point to the previous node.

  3. Merge the Two Halves: We merge the first half and the reversed second half by interleaving their nodes. We iterate through both halves simultaneously, alternating between adding a node from the first half and a node from the reversed second half to the reordered list.

Time Complexity Analysis

  • Finding the Middle: The slow and fast pointer technique iterates through the list once, taking O(n) time, where n is the number of nodes in the list.
  • Reversing the Second Half: Reversing the second half also iterates once through the second half of the list, which is approximately n/2 nodes. This also takes O(n) time.
  • Merging the Two Halves: The merging process iterates through approximately n/2 nodes from each half, taking O(n) time.

Therefore, the overall time complexity of the algorithm is O(n).

Space Complexity Analysis

The algorithm uses a constant amount of extra space for pointers (slow, fast, cur, pre, t). It does not use any auxiliary data structures that grow with the size of the input. Thus, the space complexity is O(1).

Code Implementation Details (Python3 Example):

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reorderList(self, head: Optional[ListNode]) -> None:
        #Find the middle
        fast = slow = head
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
 
        #Reverse the second half
        cur = slow.next
        slow.next = None  #Separate the two halves
        pre = None
        while cur:
            temp = cur.next #Store the next node
            cur.next = pre #Reverse the link
            pre = cur      #Move to the next node to reverse
            cur = temp     #Move to the next node to process
 
        #Merge the two halves
        cur = head
        while pre:
            temp = pre.next #Store the next node of the reversed list
            pre.next = cur.next #Link the reversed node to the next of the first half
            cur.next = pre     #Link the first half node to the reversed node
            cur = cur.next     #Move to the next node in the first half
            pre = temp         #Move to the next node in the reversed half

The other language implementations follow the same three-step process, differing only in syntax and data structure handling specific to each language. The core logic remains consistent.