使用方法为双指针法和递归法,双指针法关键点在于掌握好pre指针和cur指针的关系,递归法关键点在于递归时的输入参数的关系。递归法的逻辑与双指针法相同,只是代码更简洁一点。
双指针法:时间复杂度:O(n),空间复杂度:O(1)
双指针法思路:
- 定义指针cur指向头节点,定义指针pre指向cur的前一个节点(NULL)。
- 当当前的指针cur不为NULL时,将该指针的下一个节点改为指向前一个节点,即pre。注意,在更改顺序之前,需要创建一个tmp指针保存cur->next,使cur可以继续遍历,防止链表断裂。
- pre指针向后移动一位,即cur指针的位置。cur指针向后移动一位,即tmp指针的位置。重复步骤2。
- 最后返回新的头节点pre,或者赋给head,返回新的head。
双指针法代码:
/**
* 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* cur = head;
ListNode* pre = NULL;
ListNode* tmp = NULL;
while (cur != NULL) {
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
head = pre;
return head;
}
};
递归法:时间复杂度:O(n),空间复杂度:O(n)
递归法思路:
- 定义了一个辅助函数reverse,它接受两个指针参数cur和pre,分别表示当前节点和当前节点的前一个节点。reverse函数的功能是反转以cur为头结点的链表,并将反转后的链表的头结点返回。如果cur为NULL,则表示已经反转完了整个链表,此时返回pre,即反转后链表的头结点。
- 在主函数reverseList中调用reverse函数,并将链表头结点和NULL作为参数传入。NULL表示头节点的前一个节点为NULL,也就是反转后链表的尾部。
- 最后返回反转后的链表的头结点,这样就完成了链表反转的功能。
递归法代码:
/**
* 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* reverse(ListNode* cur, ListNode* pre) {
if (cur == NULL)
return pre;
ListNode* tmp = cur->next;
cur->next = pre;
return reverse(tmp, cur);
}
ListNode* reverseList(ListNode* head) {
return reverse(head, NULL);
}
};