力扣 206
经验:定义:ListNode fast = head,slow = head;亦可
反转错误:
1、循环截止的条件往往是跑在最前面的指针为空(就不能继续遍历next了),在更新了cur之后,再next可能就有段错误(Segmentation Fault)。(访问不被允许访问的内存位置),所以暂存tmp在更新之前。
2、定义ListNode pre = nullptr就是空的,ListNode pre = new Listnode(0)就会有个数值为0的结点。虚拟头结点可以用new,反转单纯用个指针得设nullptr.
1、双指针
初始化两个指针 cur (head) pre(null),遍历结束的时候pre指向最后一个,cur指向Null,不需要再反转指向啦、tmp临时保存cur的下一个节点,不然先反转cur之后就找不到了
cur != null时继续循环,别搞反啦;pre先移动到cur,cur再移到tmp
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//双指针
ListNode* pre = nullptr;
ListNode* cur = head;
ListNode* tmp;//先定义
while(cur != nullptr){
tmp = cur->next;
cur->next = pre;
pre = cur;//pre先移动到cur,cur再移到tmp
cur = tmp;
}
return pre;
}
};
时间复杂度: O(n)
空间复杂度: O(1)
2、递归
直到有一个return.注意两处reverse传参,思路来自于双指针
class Solution {
public:
ListNode* reverse(ListNode* pre, ListNode* cur){
//截止条件,跳出遍历,和之前并列关系还不同,所以不必else
if(cur == nullptr) return pre;
//否则继续
ListNode* tmp = cur->next;
cur->next = pre;
return reverse(cur, tmp);//这里没有先后,是一起的
//移动,递归
}
ListNode* reverseList(ListNode* head) {
return reverse(nullptr, head);
}
};