题目描述
给定一个单链表 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
解法一:翻转链表 + 合并链表 + 查询中间节点
观察后发现可以先找到链表的中间节点 aTail(对于节点数为偶数的链表,取两个中间节点中的第一个),通过中间节点将链表分为链表 a 和链表 b,链表 a 的范围是从原链表的头部到 aTail(包括 aTail),链表 b 的范围为 aTail.Next 到链表末尾。然后翻转链表 b,然后可以合并链表 a 和链表 b。
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
|
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reorderList(head *ListNode) {
if head == nil || head.Next == nil {
return
}
aTail := middleNode(head)
b := aTail.Next
aTail.Next = nil // 断开 a 和 b 的连接
b = reverseList(b)
mergeList(head, b)
return
}
// 取以 head 为头节点的链表的中间节点
func middleNode(head *ListNode) *ListNode{
if head == nil {
return head
}
slow, fast := head, head
for fast.Next != nil && fast.Next.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
return slow
}
func reverseList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
var prev *ListNode
cur := head
for cur != nil {
next := cur.Next// 先记录下一个节点
cur.Next = prev
prev = cur
cur = next// 使 cur 指向下一个节点
}
return prev
}
func mergeList(a *ListNode, b* ListNode) *ListNode {
head := a
for a != nil && b != nil {
next := a.Next// 记录 a 要指向的下一个节点
a.Next = b// 更改 a 的指向
b = b.Next// 更改 b 的指向
// a.Next.Next 此时存储的是改变前的 b,这行代码必须在 `b=b.Next` 之后执行
a.Next.Next = next
a = next// 使 a 指向链表 a 的下一个节点
}
return head
}
|
拓展:对于节点数为偶数的链表,aTail 能不能取两个中间节点的第二个节点?
总结
- 当需要更改某一节点的下一个节点的指向时,先存储这个节点的下一个节点的信息,然后马上更改这个节点的下一个节点。