迭代解法
思路: 定义两个指针,分别指向两个相邻的结点,pre指针指向较前的那个结点,cur指针指向较后的那个结点,每次将cur->next更新为pre即可。
注意事项: 由于链表不支持随机访问,只有通过上一个结点的next指针才能访问当前结点,再通过当前结点的next指针才能访问下一个结点,所以如果仅修改cur的next指针,就丢掉了cur后面结点的索引,就无法继续处理后续的结点了。
解决方法 : 在修改cur的next指针前,让一个新的变量记录一下cur的下一个结点,这样处理就不会丢失cur之后的结点了。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *pre=NULL,*cur=head;
while(cur != NULL){ //当cur指针不为空时
ListNode *next=cur->next;
cur->next=pre;
pre=cur;
cur=next;
}
return pre;
}
};
递归解法:
递归条件:
翻转以head为头结点的链表,首先需要得到翻转完成的以head->next为头结点的子链表,要得到以head->next为头结点的子链表,首先需要得到翻转完成的以head->next->next为头节点的子链表…一直这样递归下去,直到遇到终止条件。
终止条件
当到达最后一个结点时,由于最后一个结点之后不存在子链表了,所以不会往下继续递归了,此时开始逐层返回。返回的同时处理指针指向。
逐层返回时,指针的处理方法:
假设当前结点为head,head结点之后的结点已经翻转完毕了,现在就剩先head结点没有翻转了,所以在本次返回中,只要处理一下head结点的翻转就好了,即:将已经反转好的子链表头节点的next指针指向head结点,head的next指向NULL,然后就完成了整个链表的翻转。如图:
我对递归的理解是:
比如一项工作需要ABC共同完成,我和A说:你帮我完成一下这个工作,于是A对B说:你帮我完成一下这个工作,没有你B的工作成果,我A没办法开始,于是B对C说:你帮我完成一下这个工作,没有你C的工作成果,我B没办法开始。由于C的工作可以直接开始,不需要等待别的工作成果才能开始,所以任务被传达到了C之后,C开始工作,完成了之后将工作成果交给B,此时B可以工作了,完成之后将工作成果交给A,于是A开始工作,A完成之后,整个任务就圆满结束了。
代码实现:
//递归解法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL || head->next == NULL) return head;
ListNode* p=reverseList(head->next);
head->next->next=head;
head->next=NULL;
return p;
}
};
注:判断条件中:
- head->next == NULL是递归终止条件
- head == NULL是处理特殊情况,如果传入的链表是NULL,则直接返回NULL,如果不处理就会产生空指针异常的错误。因为head为空,再取head->next就会出错。
注:这里的ListNode* p保存的就是新链表的头,在整个返回过程中,P指向的链表一直在发生变化,但是P的值一直没有改变,等到返回到最顶层之后,也就是任务的最开始时,P指向的链表就是整个反转后的链表。
递归的具体细节:
呼~,我终于班门弄斧一回了。