22
22
23
23
### 1. 迭代
24
24
25
- 顺序遍历当前节点,将当前节点的前后指针进行交换,也就是将当前节点的 ` next ` 指针指向前一个节点 。
25
+ 1 . 使用两个指针 ` pre ` 和 ` cur ` 进行迭代。 ` pre ` 在 ` cur ` 前面。初始时, ` cur ` 指向 ` None ` , ` pre ` 指向 ` head ` 。
26
26
27
- 由于当前节点没有引用前一个节点,所以在更改指针指向之前必须先把前一个节点保存下来。并且由于更改之后,当前节点的后一个节点失去了引用,所以更改指针指向前,还要将当前节点的后一个节点保存下来。
27
+ 2 . 将 ` cur ` 和 ` pre ` 的前后指针进行交换,指针更替顺序为:
28
+ 1 . 使用 ` next ` 指针保存前面节点 ` pre ` 的后一个节点,即 ` next = pre.next ` ;
29
+ 2 . 断开前面节点 ` pre ` 的后一节点链接,将 ` pre ` 的 ` next ` 指针指向当前节点 ` cur ` ,即 ` pre.next = cur ` ;
30
+ 3 . ` cur ` 向前移动一步,移动到 ` pre ` 位置,即 ` cur = pre ` ;
31
+ 4 . ` pre ` 向前移动一步,移动到之前 ` next ` 指针保存的位置,即 ` pre = next ` 。
32
+ 3 . 继续执行第 2 步中的 1、2、3、4。
33
+ 4 . 最后等到 ` pre ` 遍历到链表末尾,即 ` pre == None ` ,时,` cur ` 所在位置就是反转后链表的头节点,返回新的头节点 ` cur ` 。
28
34
29
- 所以指针更替顺序为 :
35
+ 使用迭代法反转链表的示意图如下所示 :
30
36
31
- 1 . 保存前一个节点 ` prev ` ;
32
- 2 . 遍历到当前节点 ` curr ` ;
33
- 3 . 保存当前节点 ` curr ` 的后一个节点 ` next ` ;
34
- 4 . 当前节点的 ` next ` 指针指向前一个节点;
35
- 5 . 前一个节点 ` prev ` 移动到当前节点(保存前一个节点);
36
- 6 . 当前节点继续向后遍历到 next 位置(遍历当前节点)。
37
- 7 . 继续执行 3、4、5、6。
38
-
39
- 上述步骤执行到第 4 步时,当前节点 ` curr ` 和 ` next ` 就完成了反转,此时 ` next ` 指向了 ` curr ` ,继续向下执行,就会不断的进行反转。最后返回新的头节点。
37
+ ![ ] ( https://qcdn.itcharge.cn/images/20220110102335.png )
40
38
41
39
### 2. 递归
42
40
43
- 假设链表为 $n_1 → n_2 → … → n_ {k-1} → n_k → n_ {k+1} → … → n_ {m-1} → n_m → ∅$ 。
44
-
45
- 递归将 $n_2 → … → n_ {k-1} → n_k → n_ {k+1} → … → n_ {m-1} → n_m → ∅$ 进行反转,即将 ` head.next ` 为头节点的链表进行反转,并返回该链表的头节点。然后再改变 ` head ` 和 ` head.next ` 的指向关系,完成最终反转。
46
-
47
- 递归反转其实是通过栈遍历到末尾,先从末尾开始反转,先反转 $n_ {m-1} → n_m → ∅$ ,再反转 $n_ {m-2} → n_ {m-1} → n_m → ∅$,再反转 ...
48
-
49
- $n_ {m-1} → n_m → ∅$ 反转的顺序为:
41
+ 具体做法如下:
50
42
51
- 1 . $n_ {n-1}$ 的 ` next ` 的 ` next ` (即 $n_m$)指向 $n_ {m-1}$。
52
- 2 . 再将 $n_ {m-1}$ 的 ` next ` 指向 $∅$。
53
- 3 . 返回新的头节点 $n_m$。
43
+ - 首先定义递归函数含义为:将链表反转,并返回反转后的头节点。
44
+ - 然后从 ` head.next ` 的位置开始调用递归函数,即将 ` head.next ` 为头节点的链表进行反转,并返回该链表的头节点。
45
+ - 递归到链表的最后一个节点,将其作为最终的头节点,即为 ` new_head ` 。
46
+ - 在每次递归函数返回的过程中,改变 ` head ` 和 ` head.next ` 的指向关系。也就是将 ` head.next ` 的` next ` 指针先指向当前节点 ` head ` ,即 ` head.next.next = head ` 。
47
+ - 然后让当前节点 ` head ` 的 ` next ` 指针指向 ` None ` ,从而实现从链表尾部开始的局部反转。
48
+ - 当递归从末尾开始顺着递归栈的退出,从而将整个链表进行反转。
49
+ - 最后返回反转后的链表头节点 ` new_head ` 。
54
50
55
- 这样就变成了 $∅ ← n _ {m-1} ← n_m$,就完成了末尾的反转。
51
+ 使用递归法反转链表的示意图如下所示:
56
52
57
- 从末尾再依次顺着递归栈的退出,将整个链表进行反转。最后返回新链表的头节点。
53
+ ![ ] ( https://qcdn.itcharge.cn/images/20220110112149.png )
58
54
59
55
## 代码
60
56
@@ -63,14 +59,14 @@ $n_{m-1} → n_m → ∅$ 反转的顺序为:
63
59
``` Python
64
60
class Solution :
65
61
def reverseList (self , head : ListNode) -> ListNode:
66
- prev = None
67
- curr = head
68
- while curr != None :
69
- next = curr .next
70
- curr .next = prev
71
- prev = curr
72
- curr = next
73
- return prev
62
+ cur = None
63
+ pre = head
64
+ while pre != None :
65
+ next = pre .next
66
+ pre .next = cur
67
+ cur = pre
68
+ pre = next
69
+ return cur
74
70
```
75
71
76
72
2 . 递归
@@ -80,12 +76,13 @@ class Solution:
80
76
def reverseList (self , head : ListNode) -> ListNode:
81
77
if head == None or head.next == None :
82
78
return head
83
- newHead = self .reverseList(head.next)
79
+ new_head = self .reverseList(head.next)
84
80
head.next.next = head
85
81
head.next = None
86
- return newHead
82
+ return new_head
87
83
```
88
84
89
85
## 参考资料
90
86
91
87
- 【题解】[ 反转链表 - 反转链表 - 力扣] ( https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode-solution-d1k2/ )
88
+ - 【题解】[ 【反转链表】:双指针,递归,妖魔化的双指针 - 反转链表 - 力扣(LeetCode)] ( https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-shuang-zhi-zhen-di-gui-yao-mo-/ )
0 commit comments