力扣一题 206.反转链表

233 阅读2分钟

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

image-20211102145530166.png

image-20211102145547471.png

分析

本题难度为简单,进阶要求分别使用递归和迭代来完成反转

①迭代

链表的反转使用迭代法是最为容易的,只需要维护好三个指针,分别记录上一个节点的位置,当前节点的位置,以及下一个节点的位置,之后从第二个节点开始遍历链表,完成反转即可

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)前

image-20211102152546118.png

  • 调用reverseList(head.next)后

所以reverseList()中只需要把图中红线的这一部分处理一下即可

image-20211102152611530.png

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;
    }
}