143. Reorder List


LeetCode 143. 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]

Method 1

【O(n)time∣O(1)space】
package Leetcode.LinkList;

/**
 * @author zhengstars
 * @date 2024/03/11
 */
public class ReorderList {
  public static void reorderList(ListNode head) {
    // if the list only has one or no elements, just return it
    if (head == null || head.next == null) {
      return;
    }

    // initialization of slow and fast pointers
    ListNode slow = head;
    ListNode fast = head;

    // move fast pointer twice as fast as the slow pointer
    // when fast reaches the end, slow is at the middle
    while (fast.next != null && fast.next.next != null) {
      slow = slow.next;
      fast = fast.next.next;
    }

    // The 'preMiddle' node is defined as the middle node of the original list.
    // slow is at the middle node of the original list now.
    ListNode preMiddle = slow;

    // Reverse the second half of the list using the method from the first piece of code.

    // Initialize the previous node as null.
    ListNode prev = null;
    // Set the current node as the first node of the second half of the list.
    ListNode curr = slow.next;

    // This loop is to reverse the second half of the list
    while (curr != null) {
      // temporarily store the next node of the current node.
      ListNode next = curr.next;
      // point the next of the current node to the previous node, realizing the reverse.
      curr.next = prev;
      // move the previous node to the current node, preparing for next reverse.
      prev = curr;
      // move the current node to the next node, preparing for next reverse.
      curr = next;
    }

    // Insert the reversed second half list to the middle of the original list.
    preMiddle.next = prev;

    // Reset the 'slow' node to the head of the original list, preparing for the merge.
    // Reset the 'fast' node to the head of the reversed second half list, preparing for the merge.
    slow = head;
    fast = preMiddle.next;

    // This loop is to merge the two halves of the list.
    while (slow != preMiddle) {

      // Before the merge, move the 'fast' node from the second half list.
      preMiddle.next = fast.next;

      // Connect the 'fast' node to be merged, to the rest of the merged list.
      fast.next = slow.next;

      // Insert the 'fast' node to the merged list after the 'slow' node.
      slow.next = fast;

      // Move the 'slow' node to the next of the 'fast', preparing for the next merge.
      slow = fast.next;

      // Point the 'fast' node to the next to be merged node from the second half list, preparing for the next merge.
      fast = preMiddle.next;

    }
  }

  public static void main(String[] args) {
    // create a list with 6 nodes
    ListNode head2 = new ListNode(1);
    head2.next = new ListNode(2);
    head2.next.next = new ListNode(3);
    head2.next.next.next = new ListNode(4);
    head2.next.next.next.next = new ListNode(5);
    head2.next.next.next.next.next = new ListNode(6);
    // reorder the list
    reorderList(head2);
    // print the list, expecting output: 1->6->2->5->3->4
  }
}







Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • 2379. Minimum Recolors to Get K Consecutive Black Blocks
  • 2471. Minimum Number of Operations to Sort a Binary Tree by Level
  • 1387. Sort Integers by The Power Value
  • 2090. K Radius Subarray Averages
  • 2545. Sort the Students by Their Kth Score