例题
给你单链表的头节点 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先移动到curcur再移动到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);
}
};
687





