反转链表
题目描述
给你单链表的头节点
head
,请你反转链表,并返回反转后的链表。
思路
面试常考的题型,这里带来两种做法,一种双指针,一种迭代法。
双指针法
第一次看到题目时,我第一时间想到的是,先从第一个结点找到最后一个,然后再依次翻转。但是这样的时间复杂度就是O(2n)了。
为什么不能第一次遍历的时候就处理好所有翻转呢?定义两个指针
- pre:指向当前结点的前一个结点
- cur:指向当前结点
这样这需要一对对处理即可,难点在于如何进行结点的更替。
代码如下:
c
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* tmp;
ListNode* cur = head;
ListNode* pre = nullptr; //头节点的pre指向null
while(cur){
tmp = cur->next; //保存cur的下一个结点,因为下一步要修改
cur->next = pre;
//update
pre = cur; // 更新结点,从后往前更新
cur = tmp;
}
return pre;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
迭代法
迭代法的本质思路其实跟双指针是一样的,不同点在于使用了n栈的空间。
如果可以理解双指针,理解迭代法应该是更加轻松才对。
代码如下:
c
ListNode* reverseList(ListNode* head) {
return reverse(nullptr,head);
}
ListNode* reverse(ListNode* pre, ListNode* cur)
{
if(cur == nullptr)return pre; //终止条件
ListNode* tmp = cur->next;
cur->next = pre;
return reverse(cur,tmp);
}
- 时间复杂度:O(n)
- 空间复杂度:O(n)