定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
思路1:
直观思路,定义两个指针,一个指向当前节点,一个指向前一个节点,每次把当前节点的next指向前一个节点,然后当前指针指向变换前的next,前一个指针指向当前指针。重复这个过程,直到当前指针指向nullptr
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* cur = head;
ListNode* pre = nullptr;
while(cur) {
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};
思路2:
逆向思路,递归。函数的签名是ListNode reverseList(ListNode head),简记为f(x)=y,其中y表示返回值头节点ListNode*,x表示入参head。显然有f(x)==f(x.next),即有这种形式的代码
ListNode* reverseList(ListNode* head) {
if(head == nullptr) return nullptr;
ListNode* newHead = reverseList(head->next);
return newHead;
}
现在需要处理指针反转的代码:整体考虑f(x)的功能,f(x)是把头节点为x的链表反转。上面第三行代码执行完之后,可以认为头节点为x.next的链表已经反转了。所以现在只剩一个节点没有处理就是最开始的head。把这个节点处理掉就完工了。如何反转x和x.next?很显然有x.next.next = x。x = nullptr。反映在实际代码中就是如下代码:
ListNode* reverseList(ListNode* head) {
if(head == nullptr) return nullptr;
ListNode* newHead = reverseList(head->next);
//反转head和head->next
head->next->next = head;
head = nullptr;
return newHead;
}