①使用快慢指针进行反转链表
(补充知识:反转数组是使用左右双指针指针。反转链表使用的是快慢双指针指针)
1.双指针slow、fast的作用
slow表示箭头指向的终点,fast表示箭头指向的起点。fast->next = slow修改箭头指向
双指针是反转链表的核心,即:修改链表指向
2.记录fast->next(解释为什么需要第三个变量)
所记录的fast->next,只是为了能够完整的遍历整个链表。为了能够更新slow、fast
当修改指向之后:
slow = fast;
fast = fast_next;
fast_next = fast->next;
其实链表题目一般写完逻辑,可以自己模拟一下算法。很容易发现需要多少个变量(很容易得出是否缺少变量,第三个变量也可以据此模拟得出)
3.虚拟头结点
虚拟头结点的作用(与文章:移除链表元素一样)
本质:循环不变量,避免分类讨论
本题slow一开始就是指向虚拟头节点
4.图片展示全过程
遍历终止条件是fast==NULL,最终图片fast指向NULL的时候,会舍弃最后一块NULL。
②代码实现(注释很详细)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution
{
public:
ListNode* reverseList(ListNode* head)
{
//链表不需要反转,直接结束
//这种操作称为剪枝操作,遇到特殊情况可得结果的时候,直接结束!
if(head==NULL||head->next==NULL)return head;
ListNode *slow=NULL;//其实这里就是虚拟头结点了!//只是表示虚拟头结点的方式特殊
ListNode *fast=head;
ListNode* fast_next;//记录fast->next,才能在fast修改指向之后,访问到链表的其他元素
while(fast){//fast指向NULL的时候说明反转结束(遍历结束)
fast_next = fast->next;
fast->next = slow;
slow = fast;
fast = fast_next;
}
head = slow;//fast指向NULL,fast的前一个当然是slow也就是新的头结点,只是fast指向NULL的时候没有修改指向
return slow;
}
};