给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
分析
本题难度为简单,进阶要求分别使用递归和迭代来完成反转
①迭代
链表的反转使用迭代法是最为容易的,只需要维护好三个指针,分别记录上一个节点的位置,当前节点的位置,以及下一个节点的位置,之后从第二个节点开始遍历链表,完成反转即可
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null) return null;
// 上一个节点、当前节点,下一个节点
ListNode last,cur,tep;
last=head;
cur=last.next;
tep=null;
while(cur!=null){
// 处理头节点,否则会出现环
if(tep==null) last.next=null;
tep=cur.next;
cur.next=last;
last=cur;
cur=tep;
}
return last;
}
}
②递归
本题使用递归来解答可以得到更加简洁的代码。对于递归,很多初学者可能都无法理解,每次都不知道怎么写出递归代码。
对于递归,我有自己的一个理解方法:我们可以把递归理解成“甩锅”,本来是我的任务,但我只做了一部分,剩下的都甩给别人了。就比如说reverseList()这个方法,它本来的任务是完成链表的反转并返回新链表的头结点,但具体到实现方法中,则调用了reverseList(head.next),其实就是它只负责了头结点和它的后续结点的反转,剩下的任务都交给了reverseList(head.next)来完成,最后返回reverseList(head.next)的返回值res即可,这波呀,这波是窃取劳动果实呀
其实从上面的分析就可以看到,递归最重要的步骤就是递归方法的定义,也就是说reverseList()这个方法到底要实现什么功能,定好了这一步之后,后面的实现就相对简单了
- 调用reverseList(head.next)前
- 调用reverseList(head.next)后
所以reverseList()中只需要把图中红线的这一部分处理一下即可
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode res=reverseList(head.next);
// 修改头节点和下一个节点的指针指向
head.next.next=head;
head.next=null;
return res;
}
}