給定單鏈表 L₀→L₁→…→Lₙ₋₁→Lₙ,重排為 L₀→Lₙ→L₁→Lₙ₋₁→L₂→Lₙ₋₂→…。要求在原鏈表上操作,不修改節點值,空間複雜度 O(1)。
public void reorderList(ListNode head) {
if (head == null || head.next == null || head.next.next == null) return;
// 1. 計算長度並找到中點
int len = 0;
ListNode cur = head;
while (cur != null) { len++; cur = cur.next; }
int half = (len + 1) / 2;
cur = head;
ListNode second = head.next;
for (int i = 1; i < half; i++) {
cur = second;
second = second.next;
}
cur.next = null; // 斷開前半部分
// 2. 反轉後半部分鏈表
ListNode secondHead = second;
cur = second.next;
secondHead.next = null;
while (cur != null) {
ListNode temp = cur;
cur = cur.next;
temp.next = secondHead;
secondHead = temp;
}
// 3. 交替合併
ListNode cur1 = head, cur2 = secondHead;
while (cur2 != null) {
ListNode next1 = cur1.next;
ListNode next2 = cur2.next;
cur2.next = cur1.next;
cur1.next = cur2;
cur1 = next1;
cur2 = next2;
}
}
(len + 1) / 2 保證奇數長度時前半部分多一個節點。secondHead, cur, temp)無需額外空間。next1, next2,再重新鏈接,避免斷鏈。輸入:1→2→3→4
中點後斷開:1→2 和 3→4
反轉後半:4→3
交替合併:1→4→2→3
本題綜合考察鏈表基本操作:找中點、反轉、合併。掌握這三個核心步驟的邊界條件(空鏈表、單節點、雙節點)是寫出健壯代碼的關鍵。