剑指Offer-17-反转链表

项目地址:https://github.com/SpecialYy/Sword-Means-Offer

题目

输入一个链表,反转链表后,输出新链表的表头。

解析

预备知识

链表之类的题目,一般都会涉及到指针的指向问题,对于这类问题,我们可以通过画图来找思路,空想总是比不过烂笔头。注意链表的三种情况,做到万无一失。

  1. 输入的链表头指针是null
  2. 输入的链表只有一个结点
  3. 输入的链表有多个结点
思路一

我们先画图看看如何反转链表。
这里写图片描述
通过以上分析我们发现,当对当前节点改变其指向为前一个节点,所以我们需要一个指针pre来指向前一个节点。改变当前节点的next后,链表会就此断开,我们无法获得后一个将要考察的节点,所以还需一个指针after指向后一个节点。所以总结如下:

  1. pre始终指向已反序的最后一个节点
  2. middle始终指向正在考察节点
  3. after始终指向待反序的第一个节点,也就是middle之后

当middle指针指向的节点不为空时,我们需要用after来保存它下一个节点,防止链表断开后,无法继续后移。middle的next指向pre实现反序,然后middle和pre同时后移一步即可,此时middle指向下一个待考察的节点,直到middle指向空为止,说明链表已完成反序操作。

    /**
     * 利用三个指针进行链表反序
     * @param head
     * @return
     */
    public static ListNode ReverseList1(ListNode head) {
        //pre始终指向已反序的最后一个节点
        ListNode pre = null;
        //middle始终指向正在考察节点
        ListNode middle = head;
        //after始终指向待反序的第一个节点,也就是middle之后
        ListNode after = null;
        while(middle != null) {
            //更新after
            after = middle.next;
            //对考察的节点进行反序
            middle.next = pre;
            //更新pre
            pre = middle;
            //后移middle, 换下一个待考察节点
            middle = after;
        }
        //因为pre始终指向已反序的最后的一个节点
        return pre;
    }
思路二

还是上面的想法,只不过我们这次充分利用head来代替middle作用,我们赋予head新的语义,使其始终指向已完成反序的最后一个节点。

    /**
     * 充分利用head指针和外加2个辅助指针
     * @param head
     * @return
     */
    public static ListNode ReverseList2(ListNode head) {
        ListNode pre = null;
        ListNode after = null;
        while(head != null) {
            after = head.next;
            head.next = pre;
            pre = head;
            head = after;
        }
        return pre;
    }
思路三

递归思想
我们使其先走到链表的末尾,确保每次回溯时都返回最后一个节点的指针。同时从倒数第二个结点开始反序。
head.next.next = head;是指使当前节点的下一个节点指向自己
head.next = null断开与下一个节点的联系,完成真正的反序操作
如图所示
这里写图片描述

    /**
     * 牛逼的递归实现
     * @param head
     * @return
     */
    public static ListNode ReverseList3(ListNode head) {
        if(head == null || head.next == null) {
            return head;
        }
        ListNode reverseHead = ReverseList3(head.next);
        head.next.next = head;
        head.next = null;
        return reverseHead;
    }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值