题目描述
来源:leetcode_hot100_206
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
提示:
链表中节点的数目范围是 [0, 5000]
-5000 <= Node.val <= 5000
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
错误示范
思路:大体思路正确,见正解一处
/**
* 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) {
stack<ListNode *> stp;
ListNode *p = head;
while (p != nullptr)
{
stp.push(p);
p = p->next;
}
p = head;
while (!stp.empty())
{
p->val = stp.top()->val;
stp.pop();
p = p->next;
}
return head;
}
};
错误原因:解答错误,因为我第二个while时直接修改了链表中的值,而stack里存的仅仅是指针的备份而非值的备份
正解一(栈)
思路:利用栈将链表的值从头到尾装入栈中,再挨个弹出修改结点的值,利用栈的先进后出特性
/**
* 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) {
stack<int> stval;
ListNode* p=head;
while(p!=nullptr){
stval.push(p->val);
p=p->next;
}
p=head;
while(p!=nullptr){
p->val=stval.top();
stval.pop();
p=p->next;
}
return head;
}
};
正解二(递归)
思路:力扣精选题解里有图比较好理解,光看文字不好理解
终止条件是当前节点或下一节点为nullptr
改变节点指向 p->next->next=p
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* p=head;
if(p==nullptr || p->next==nullptr){//由reverseList(p->next)遍历到最后一个结点时会返回cur=5
return p;
}
//cur不管怎么递归返回永远指的是最后一个节点,例如[1,2,3,4,5]则cur指向的节点的val永远为5
ListNode* cur=reverseList(p->next);//先从前向后遍历到最后一个节点
//如果链表是 1->2->3->4->5,那么此时的cur就是指向5的指针
//又因为这句cur(=5)=reverseList(p->next)这里的p为指向4的指针
p->next->next=p;//p->next就是5的结点 这样p->next->next(就是5结点的next)就变4了
p->next=nullptr;//防止链表循环,此时4->5的指针应设置为4->空
return cur;//cur一直保持指向最后一个结点直到结束
}
};