题目
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
示例
示例 1:
输入:head = [1,2,3,4,5] 输出:[5,4,3,2,1]示例 2:
输入:head = [1,2] 输出:[2,1]示例 3:
输入:head = [] 输出:[]
分析
迭代法
逐个改变节点的指向,非常适合处理大规模链表。
时间复杂度:O()
空间复杂度:O(1)
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr; // 初始化前驱指针为 null
ListNode* curr = head; // 当前指针指向头节点
while (curr) {
ListNode* nextTemp = curr->next; // 暂存当前节点的下一个节点
curr->next = prev; // 将当前节点的 next 指针反转,指向前一个节点
prev = curr; // 将 prev 移动到当前节点
curr = nextTemp; // 将 curr 移动到下一个节点(原链表的下一个节点)
}
return prev; // prev 成为新的头节点
}
};
递归法
假设链表从第二个节点开始已经反转好了,然后将第一个节点接到已反转链表的尾部。
递归过程举例
假设链表为:
1 -> 2 -> 3 -> nullptr
初始调用:
reverseList(1)
head
为节点 1,不满足终止条件,递归调用reverseList(2)
第二次调用:
reverseList(2)
head
为节点 2,不满足终止条件,递归调用reverseList(3)
第三次调用:
reverseList(3)
head
为节点 3,满足head->next == nullptr
,返回节点 3回到第二次调用:
newHead
为节点 3。将2->next->next
(即3->next
)设置为节点 2,实现链接3 -> 2
。设置2->next = nullptr,
返回newHead
(节点 3)。回到第一次调用:
newHead
仍为节点 3。将1->next->next
(即2->next
)设置为节点 1,实现链接2 -> 1
。设置1->next = nullptr,
返回newHead
(节点 3)。最终链表反转为:
3 -> 2 -> 1 -> nullptr
。
递归方法代码更简洁,但 递归深度大时可能导致栈溢出。
时间复杂度:O()
空间复杂度:O()
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (!head || !head->next) return head; // 递归终止条件
ListNode* newHead = reverseList(head->next); // 反转剩余链表
head->next->next = head; // 让当前节点的下一个节点指向自己
head->next = nullptr; // 断开原来的连接
return newHead; // 返回新的头节点
}
};