最近在牛客又做到了这个题,但是实现方法和当初不一样(做完就忘),在此记录一下
方法一:在原链表上修改
这个方法用了三个指针,反转当前指针的指向后再一个一个向前挪动。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head) return head;//判空
ListNode* pre = nullptr;//前指针:记录当前节点的上一个节点
ListNode* cur = head;//现指针:记录当前节点
ListNode* Next = head->next;//后指针:记录当前节点的下一个结点
while(cur){//遍历完整个链表
cur->next = pre;//直接把指向反转就行
pre = cur;//通过赋值操作向前移动,前指针移动到现指针的位置
cur = Next;//现指针移动到后指针的位置
if(Next) Next = Next->next;//后指针在可以的情况下移动到后指针的下一个结点
}
return pre;
}
};
方法二:另起炉灶
就是一个一个新建结点,当前新建的节点指向上一次新建的结点,这样就完成了反转。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @return ListNode类
*/
ListNode* ReverseList(ListNode* head) {
// write code here
if(!head){//判空
return nullptr;
}
ListNode* ans = new ListNode(head->val);//先建立一个结点作为依托,也就是原链表的头结点
ListNode* cur = head->next;//从第二个节点开始
while(cur){
ListNode* Node = new ListNode(cur->val);//新建一个结点,值为原链表中当前结点的值
Node->next = ans;//指向上一次创建的结点
ans = Node;//移动到这次的结点,作为下次的前辈(呃呃)
cur = cur->next;//原链表指针移动到下一个
}
return ans;
}
};
//(很明显这种方法比较蠢,还是记住第一个吧...)
方法三:递归
经典递归,三要素:
- 函数功能:将链表翻转;
- 结束条件:当翻转至最后一个结点时,会发生单结点或空链表的情况,此时结束递归,返回头结点;
- 等价关系:或者说是每一步的方法,通过一个中介将当前结点和下一个结点的指向反转即可。
直接上代码:
/**
* 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 == nullptr || head->next == nullptr){//结束条件
return head;
}
ListNode* res = reverseList(head->next);//函数功能:将链表翻转
//等价关系:通过中介it将head和head->next的指向反转,然后将翻转之后的链表返回上一级
ListNode* it = head->next;
it->next = head;
head->next = nullptr;
return res;
}
};
(递归真难啊)