🚗题目描述
给你单链表的头节点
head
,请你反转链表,并返回反转后的链表。
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]
示例 2:
输入:head = [1,2] 输出:[2,1]
示例 3:
输入:head = [] 输出:[]
注意:画图、画图、画图!数据结构画图很重要 ~
🥖解法一:三指针迭代
思路:设置三个指针,第一个置空 ListNode* temp = nullptr,第二个 pre = head指向头结点,第三个指向头结点的下一个 cur = head->next,实现翻转的关键为将pre的下一个指向temp,将temp放到pre,pre放到cur,cur往后走实现迭代,注意当cur为空时就不往后走,当pre为空时结束循环,返回值为temp作为头结点。
时间复杂度:O(n),其中 nnn 是链表的长度。需要遍历链表一次。
空间复杂度:O(1)。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr){return nullptr;}
ListNode* temp = nullptr;
ListNode* pre = head;
ListNode* cur = head->next;
while(pre){
//翻转链表
pre->next = temp;
//迭代往后走
temp = pre;
pre = cur;
if(cur)
cur = cur->next;
}
return temp;
}
};
🥖解法二:双指针迭代
思路:定义两个指针,pre和cur,pre置空,每次将cur->next指向pre进行翻转,直至pre为null,其实方法和上面那个差不多,最后返回pre作为头指针。
时间复杂度:O(n),其中 nnn 是链表的长度。需要遍历链表一次。
空间复杂度:O(1)
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr){return nullptr;}
ListNode* pre = nullptr;
ListNode* cur = head;
while(cur){
ListNode* t = cur->next;
cur->next = pre;
pre = cur;
cur = t;
}
return pre;
}
};
🥖解法三:递归
使用递归的方法一直递归到链表的最后一个结点,该结点为翻转后链表的头结点,记为ret,注意当头结点head为空或者链表元素只有一个时返回head。递归过程中,将链表分为两个部分,未翻转和已翻转的子链,实现翻转的关键为head的下一位指向head,因此为head->next->next=head;,并且要记得把head的下一位置空,不然会导致环链。
aaa这个方法感觉有点难理解TT 但是代码比较简洁
递归方法总结:
1.明确递归方法要实现什么功能? --实现链表的翻转 head->next->next=head;
2.明确递归开始结束的条件?--当head->next为nullptr时终止
3.返回给上一级什么值?--返回最后翻转头结点ret
复杂度分析
时间复杂度:O(n),其中 n 是链表的长度。需要对链表的每个节点进行反转操作。
空间复杂度:O(n),其中 n 是链表的长度。空间复杂度主要取决于递归调用的栈
图释:(递归的流程)
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr||head->next==nullptr){return head;}
ListNode* ret = reverseList(head->next);
head->next->next=head;
head->next=nullptr;
return ret;
}
};
----------------以上为三种解法,仅供参考啦~~