重排链表
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
1
| L0 → L1 → … → Ln - 1 → Ln
|
请将其重新排列后变为:
1
| L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
|
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:

1 2
| 输入:head = [1,2,3,4] 输出:[1,4,2,3]
|
快慢指针 (切成两半)+ 反转 + 交替合并
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| class Solution { public void reorderList(ListNode head) { if (head == null || head.next == null) { return; }
// 1. 找到左半部分的尾节点(中点) ListNode mid = findMiddle(head); ListNode l1 = head; ListNode l2 = mid.next; mid.next = null; // 关键:必须断开左右两条链表,否则会形成环! // 2. 反转右半部分链表 l2 = reverseList(l2); // 3. 交替合并 l1 和 l2 mergeList(l1, l2); } // 步骤 1:快慢指针找中点 private ListNode findMiddle(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } return slow; } // 步骤 2:原地反转链表 private ListNode reverseList(ListNode head) { ListNode prev = null; ListNode curr = head; while (curr != null) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; } // 步骤 3:交替合并两个链表 private void mergeList(ListNode l1, ListNode l2) { ListNode l1Temp; ListNode l2Temp; while (l1 != null && l2 != null) { // 暂存两边的下一个节点 l1Temp = l1.next; l2Temp = l2.next; // 交错穿插连接 l1.next = l2; l1 = l1Temp; l2.next = l1; l2 = l2Temp; } }
}
|