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
63
64
65
66
67
68
69
70
71
|
# 递归反转链表函数:
# 功能:反转从 head 开始,到 tail(不包含 tail)的链表部分
# 返回反转后的链表头节点 (也就是原链表从 head 到 tail 之间最后一个节点)
# head: 当前递归段的起始节点
# tail: 当前递归段的结束标记节点(即要反转的范围的下一个节点)
# tail 节点本身不参与反转,仅作为结束标记
def reverse(self, head, tail):
# --- 基本情况 (Base Cases) ---
# 当我们处理的链表段为空,或者只剩一个有效节点(加上 tail 标记)时,递归停止
# 情况 1: head == tail
# - 如果 head 和 tail 指向同一个节点,意味着我们要反转的区间是空的
# - 例如,如果原链表是 A -> B -> C,我们要反转 B 到 C (head=B, tail=C)
# 第一次递归:reverse(B, C)
# 第二次递归:reverse(C, C)此时 head == tail,返回 C
# - 或者,如果链表是 A -> B,我们要反转 A 到 B (head=A, tail=B)
# 第一次递归:reverse(A, B)
# 这种情况也包括在情况 2 中
# 情况 2: head.next == tail
# - 如果 head 的下一个节点就是 tail,说明要反转的链表段只包含 `head`
# - 例如,链表是 A -> B -> C -> D
# 我们要反转 B 到 D (head=B, tail=D)
# 第一次递归:reverse(B, D)
# 第二次递归:reverse(C, D)此时 head=C, head.next=D
# - 在这种情况下,`head` (节点 C) 就是反转后的这部分的头节点
# 直接返回 `head`,表示反转完成
if head == tail or head.next == tail:
return head
# --- 递归步骤 (Recursive Step) ---
# 核心思想:head 被插到的是递归调用 reverse(head.next, tail)
# 所返回的那个反转链表段的最前面
# 1. 递归调用:先反转 `head` 后面的部分 (`head.next` 到 `tail`)
# - `self.reverse(head.next, tail)`: 这一步会返回反转后的链表段的头节点
# 假设链表是 1 -> 2 -> 3 -> 4 -> 5, 我们要反转 1 到 5 (head=1, tail=5)
# 递归调用会先处理 2 -> 3 -> 4 -> 5
# 最终,`reverse(2, 5)` 会返回节点 4
#. 并且链表段 2 -> 3 -> 4 被反转成 4 -> 3 -> 2
# - `p` 接收这个返回的头节点(节点 4)
p = self.reverse(head.next, tail)
# 2. 执行头插法:将 `head` 插入到 `p` 指向的反转链表的前面
# - `head.next.next = head`:
# - `head.next` 是当前节点 `head` 的直接后继(在递归调用前)
# 在递归返回后,`head.next` 实际上是反转后的链表段的第一个节点
# 所以,这一行代码的意思是:将 `p` 的 `next` 指针指向 `head`
# - 以 1 -> 2 -> 3 -> 4 -> 5 (head=1, tail=5) 为例:
# 递归后,链表是 4 -> 3 -> 2,p 指向 4head 是 1
# head.next 是 2
# head.next.next = head => 2.next = 1
# 此时链表结构变为:4 -> 3 -> 2 -> 1
head.next.next = head
# 3. 更新 `head` 的 `next` 指针:
# - `head.next = tail`:
# - `head` (节点 1) 是当前处理的链表段的最后一个节点
# - 它的 `next` 指针需要指向我们传入的 `tail` 标记
# - 以 1 -> 2 -> 3 -> 4 -> 5 (head=1, tail=5) 为例:
# head.next = tail => 1.next = 5
# 链表结构变为:4 -> 3 -> 2 -> 1 -> 5
head.next = tail
# 4. 返回 `p`:
# - `p` 是反转后的链表段的头节点
# `p` 是原链表 `head.next` 到 `tail` 之间的最后一个节点
# - 这个返回值会被上一层的递归调用接收,用于继续执行头插法
# - 例如,在 1 -> 2 -> 3 -> 4 -> 5 的例子中,reverse(1, 5) 返回 p (节点 4)
# 它才是整个 1 -> 5 区间的反转后的头节点
return p
|