例题
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
双指针法
-
首先定义一个
cur
指针,指向头结点,再定义一个pre
指针,初始化为NULL
- 因为反转后
head
要指向NULL
- 因为反转后
-
然后就要开始反转了,首先要把
cur->next
节点用tmp
指针保存一下- 因为接下来要改变
cur->next
的指向了,将cur->next
指向pre
- 因为接下来要改变
-
接下来,继续移动
pre
和cur
指针(注意两者先后顺序)pre
先移动到cur
cur
再移动到tmp
-
最后,
cur
指针已经指向了NULL
,循环结束,链表也反转完毕了- 此时我们
return pre
就可以了,pre
指针就指向了新的头结点
- 此时我们
// 时间复杂度: O(n)
// 空间复杂度: O(1)
/**
* 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 *pre=NULL;
ListNode *cur=head;
while(cur)
{
ListNode *tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
};
递归法
- 递归法的逻辑其实和上述方法相同,只不过代码更简洁优雅
// 时间复杂度: O(n), 要递归处理链表的每个节点
// 空间复杂度: O(n), 递归调用了 n 层栈空间
/**
* 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) {
// 这是初始条件,即pre=NULL,cur=head
return reverse(NULL,head);
}
ListNode* reverse(ListNode *pre,ListNode *cur)
{
// 对应上述循环终止条件
if(cur==NULL)
return pre;
// 对应上述对两个指针的移动和循环过程
ListNode *tmp=cur->next;
cur->next=pre;
return reverse(cur,tmp);
}
};