题目描述
143. 重排链表
给定一个单链表 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)
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]
。
- 中点为