题目描述
给定一个单链表 L
**的头节点 head
,单链表 L
表示为:
L0 → L1 → ... → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → ...
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入: head = [1,2,3,4]
输出: [1,4,2,3]
示例 2:
输入: head = [1,2,3,4,5]
输出: [1,5,2,4,3]
提示:
- 链表的长度范围为
[1, 5 * 104]
1 <= node.val <= 1000
分析解答
解题思路
-
找到链表的中点:
- 使用快慢指针法找到链表的中点,快指针每次走两步,慢指针每次走一步。当快指针到达末尾时,慢指针恰好在链表中点。
-
反转链表的后半部分:
- 将链表中点之后的链表部分反转,以便后续的交替合并。
-
合并两部分链表:
- 依次从前半部分和后半部分取出节点交替连接,构造出所需的排列顺序。
代码实现(JavaScript)
javascript
function reorderList(head) {
if (!head || !head.next) return;
// 1. 找到链表的中点
let slow = head, fast = head;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
// 2. 反转链表的后半部分
let prev = null, curr = slow;
while (curr) {
let nextNode = curr.next;
curr.next = prev;
prev = curr;
curr = nextNode;
}
// 3. 合并两部分链表
let first = head, second = prev;
while (second.next) {
let temp1 = first.next;
let temp2 = second.next;
first.next = second;
second.next = temp1;
first = temp1;
second = temp2;
}
}
贴上我乱糟糟的笔记供后续复习。
详细步骤讲解
-
找到中点 :将链表拆分为前后两部分,以
slow
为中点,前半部分从head
开始,后半部分从slow
开始。 -
反转后半部分:
- 从
slow
开始反转链表的后半部分。 - 利用指针
prev
和curr
,将curr.next
指向prev
,不断移动指针直到链表反转完成。
- 从
-
交替合并:
- 将前半部分和反转后的后半部分交替连接。
- 每次取
first
和second
两个节点,然后更新指针顺序,使链表排列成L0 → Ln → L1 → Ln-1
的形式。
示例讲解
-
输入 :
head = [1, 2, 3, 4]
- 中点为
3
,反转后变为[1, 2]
和[4, 3]
。 - 交替合并,得到
[1, 4, 2, 3]
。
- 中点为
-
输入 :
head = [1, 2, 3, 4, 5]
- 中点为
3
,反转后为[1, 2]
和[5, 4, 3]
。 - 交替合并,得到
[1, 5, 2, 4, 3]
。
- 中点为