剑指Offer对答如流系列 - 反转链表

Posted jefferychenxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer对答如流系列 - 反转链表相关的知识,希望对你有一定的参考价值。

面试题24:反转链表

题目描述

定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点

链表结构

     public class ListNode {
        int val;
        ListNode next = null;
        ListNode(int val) {
            this.val = val;
        }
    }

问题分析

头插法是反转链表非常经典的一种手段,这里演示一下吧,毕竟这个在JDK源码中也能遇见。

核心代码如下:

    ListNode Inverse(ListNode L)
    {
        ListNode p, q;
        p = L.next;
        L.next = null;
        while (p != null)
        {
            q = p;
            p = p.next;

            q.next = L.next;
            L.next = q;
        }
        return L;
    }

这些图示来自我这篇文章的单链表逆置:头插法图解,实现方面是用C语言,如果你不懂C语言,你把 -> 理解为.

刚开始是这样
技术图片

循环前的操作
技术图片

进入循环,分别用q和p记录第一个和第二个节点
技术图片
技术图片

进入第二轮循环,这是发生重大变化的关键时期
技术图片
技术图片
技术图片

这张图调整一下
技术图片

直到链表为空.

当然除了这种方法外,我们也可以用递归进行处理,我们通过递归,到达链表的尾结点,再依次对链表进行反转操作。

反转操作很简单
技术图片

以最后的节点 6 为例

只需要把节点6后面的引用指向节点5,节点5的引用置为null
技术图片

在处理节点5的时候,将节点5后面的引用指向节点4,节点4的引用置为null,依次处理即可
技术图片

核心代码如下

        head.next.next=head;
        head.next=null;

三、问题解答

(1)头插法

    public ListNode reverseList(ListNode head) {
        if(head==null) {
            return null;
        }
        ListNode pNode=head;
        ListNode preNode=null;
        ListNode nextNode=pNode.next;
        while(nextNode!=null) {
            pNode.next=preNode;
            preNode=pNode;
            pNode=nextNode;
            nextNode=pNode.next;
        }
        pNode.next=preNode;
        return pNode;
    }

(2)递归

    public ListNode reverseList(ListNode head) {
        if(head==null || head.next==null) {
            return head;
        }
        ListNode rvsHead=reverseList(head.next);
        //找到了最后的头结点后,开始转换每个结点的指向
        head.next.next=head;
        head.next=null;
        return rvsHead;
    }

以上是关于剑指Offer对答如流系列 - 反转链表的主要内容,如果未能解决你的问题,请参考以下文章

剑指Offer对答如流系列 - 在O时间删除链表结点

剑指Offer对答如流系列 - 复杂链表的复制

剑指Offer对答如流系列 - 链表中环的入口节点

剑指Offer对答如流系列 - 链表中倒数第k个结点

剑指offer系列刷题第二篇——从尾到头打印链表和反转链表

剑指offer系列9:反转链表