代码随想录 链表:206. 翻转链表
题意:反转一个单链表。
示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
思路
改变链表中节点的走向,使链表指向上个节点,怎么做?
我们知道链表的末尾节点的 next 是空指针,那我们先搞一个空指针。然后第一个节点指向它,但是因为是单向列表,第一个节点指向空了之后他就会丢失掉原来指向的第二个节点。所以我们要先记录下来当前节点的下一个节点存起来。这样就出现了两个链表:,这两个链表都在变化。
[1] → nullptr [2] → [3] → nullptr
注意上面的 tmp 应在循环外就消失。
cpp
#include <iostream>
struct ListNode
{
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {};
ListNode(int x) : val(x), next(nullptr) {};
ListNode(int x, ListNode *p) : val(x), next(p) {};
};
ListNode *reverseList(ListNode *head)
{
ListNode *pre = nullptr;
ListNode *cur = head;
while (cur)
{
ListNode *tmp = cur->next; // 存储下个节点
cur->next = pre; // 改变方向
pre = cur; // 左指针右移
cur = tmp; // 右指针右移
}
return pre; // 当cur指向null的时候,pre在他前面,自然就是头节点了
}
int main()
{
}
AI 绘图
假设原始链表为 1 -> 2 -> 3 -> nullptr
,目标是将其反转为 3 -> 2 -> 1 -> nullptr
。
初始状态
head → [1] → [2] → [3] → nullptr
pre = nullptr
cur = head (指向 1)
步骤 1:第一次循环
- 保存
cur->next
:tmp = 2
(保存1
的下一个节点)。 - 反转指针:
cur->next = pre
(1
的next
指向nullptr
)。 - 移动
pre
和cur
:pre
移动到1
。cur
移动到tmp
(即2
)。
图形化结果:
pre → [1] → nullptr
cur → [2] → [3] → nullptr
步骤 2:第二次循环
- 保存
cur->next
:tmp = 3
(保存2
的下一个节点)。 - 反转指针:
cur->next = pre
(2
的next
指向1
)。 - 移动
pre
和cur
:pre
移动到2
。cur
移动到tmp
(即3
)。
图形化结果:
pre → [2] → [1] → nullptr
cur → [3] → nullptr
步骤 3:第三次循环
- 保存
cur->next
:tmp = nullptr
(保存3
的下一个节点)。 - 反转指针:
cur->next = pre
(3
的next
指向2
)。 - 移动
pre
和cur
:pre
移动到3
。cur
移动到tmp
(即nullptr
)。
图形化结果:
pre → [3] → [2] → [1] → nullptr
cur → nullptr
循环结束
cur
为nullptr
,循环终止。- 返回
pre
,即反转后的链表头节点3
。
最终链表:
[3] → [2] → [1] → nullptr
动态演示
初始: 1 → 2 → 3 → nullptr
Step1: 1 → nullptr | pre=1, cur=2
Step2: 2 → 1 → nullptr | pre=2, cur=3
Step3: 3 → 2 → 1 → nullptr | pre=3, cur=nullptr
关键点总结
- 指针操作:每次循环只修改当前节点
cur
的next
指针。 - 顺序移动:
pre
和cur
像"双指针"一样逐步向后滑动。 - 终止条件:
cur
为nullptr
时结束。