1、题目要求
给定单链表的头节点 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
进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?
2、题目分析
题目告诉我们这道题有两种解法:迭代法和递归法
迭代法:通过不同的指针变量,遍历整个链表,并在遍历的过程中将数据逆置并存放在一个新的链表中。
递归法:通过调用reversList函数,将链表后面的数据逆置,最后达到整个链表逆置的目的。(将一个链表head逆置,就相当于将head->next的所有数据逆置,将head->next的1所有数据逆置,就相当于将head->next->next的所有数据逆置······最后再依次返回即可)
3、代码实现
迭代法:
方法一
/**
* 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) {
ListNode*newHead=new ListNode(); //创建新的链表
newHead->next=NULL; //新链表后置为空
ListNode*p=head,*q=head; //两个游动的指针变量,先同时指向head
while(p){ //把p当作要取的数
q=q->next; //q变为p的后一个数,防止p丢失
p->next=newHead->next; //把p链接到newHead上
newHead->next=p;
p=q; //把p移动到q位置上
}
return newHead->next;
}
};
方法二
/**
* 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) {
//ListNode*newHead=new ListNode();
//newHead->next=NULL;
ListNode*curr=head,*prev=NULL;
while(curr){
ListNode*next=curr->next;
curr->next=prev;
prev=curr;
curr=next;
}
return prev;
}
};
递归法:
/**
* 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||!head->next) return head; //先判断是否为空或者只有一个结点,是的话直接返回
ListNode*newHead=reverseList(head->next);//开始递归
head->next->next=head; ①//每次递归要将传入的链表的头节点拿到逆置后的链表的尾部
head->next=NULL; ②//将逆置后的尾结点(即原来的头结点)后置为空
return newHead;
}
};
①②解释:例如1 2 3 4 5 ,我们传入reversList函数后,2 3 4 5 逆置变为 5 4 3 2 ,此时5就是newHead的头结点,而我们需要将原来的头结点head放到newHead的最后面,也就是2的后面,此时2在原结点中还是head->next,那么head->next->next=head就将head移到最后了,但移动后最后结点的后续不为空,所以我们用head->next=NULL将newHead最后置为空。