一、题目
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
二、题解思路
- 题解思路1(迭代实现)
在遍历列表时,将当前节点(Node)的 next 指针改为指向前一个元素(NodePrev)。由于节点没有引用其前一个结点,因此必须事先存储其前一个结点。在更改引用之前,还需要另一个指针来存储下一个节点( NodeNext = Node->next)。不要忘记在最后返回新的头引用( return NodePrev )!
- 题解思路2(递归实现)
递归的实现方式主要有4步:
1)如果head为空,或者只有head这一个节点,return head即可;
2)先遍历head->next为首的链表,得到一个头结点newHead;
3)把head赋值给head->next->next, head->next为空;
4)返回newHead。
三、代码实现
- C++代码实现迭代版本
/**
* Definition for singly-linked list.
* struct ListNode {
* int val; //当前节点的值(数据域)
* ListNode *next; //指向下一个结点的指针(指针域)
* ListNode(int x) : val(x), next(NULL) {} //初始化当前结点的值为x,指针为空
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head)
{
ListNode* NodePrev = nullptr; //当前结点的上一个结点
ListNode* Node = head; //当前结点
ListNode* NodeNext = nullptr; //当前结点的下一个结点
while(Node != nullptr)
{
NodeNext = Node->next; //记录当前结点的下一个结点,防止链表断开,从而进行下一次反转
Node->next = NodePrev; //把当前结点Node指向下一个结点的指针指向NodePrev(即Node的上一个结点)
NodePrev = Node; //此时,将NodePrev向后移动指向此时的Node
Node = NodeNext; //将Node向后移动,指向刚才保存的NodeNext,迭代进行下一个结点的反转
}
return NodePrev; //返回新的头结点,即可输出链表的后续内容
}
};
- C++实现递归版本
/**
* Definition for singly-linked list.
* struct ListNode {
* int val; //当前节点的值(数据域)
* ListNode *next; //指向下一个结点的指针(指针域)
* ListNode(int x) : val(x), next(NULL) {} //初始化当前结点的值为x,指针为空
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head)
{
if(head == NULL || head->next ==NULL) //链表中有0个结点或者1个结点
return head;
ListNode* newhead = reverseList(head->next); //先反转后面的链表,从最后面的两个结点开始反转,依次向前
head->next->next = head; //将后一个链表结点指向前一个结点
head->next = nullptr; //将原链表中前一个结点指向后一个结点的指向关系断开
return newhead;
}
};
完整的程序代码实现: