jdk8 list 反转_链表反转的两种实现方法,后一种击败了100%的用户!

8e1d4b3370746959510cc4a077884663.png

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

链表反转是一道很基础但又非常热门的算法面试题,它也在《剑指Offer》的第 24 道题出现过,至于它有多热(门)看下面的榜单就知道了。

8a7fcfc30bb8a623c461bc352a7b8975.png

b948467f7ad30e4aedee7ab5ee11942c.png

从牛客网的数据来看,链表反转的面试题分别霸占了【上周考过】和【研发最爱考】的双重榜单,像网易、字节等知名互联网公司都考过,但通过率却低的只有 30%,所以本文我们就来学习一下反转链表的两种实现方法。

排行榜数据:https://www.nowcoder.com/activity/oj

题目

标题:剑指 Offer 24. 反转链表

描述:定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:

输入: 1->2->3->4->5->NULL

输出: 5->4->3->2->1->NULL

LeetCode 链接:https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/

实现方式一:Stack

db55a53545ea3c4281fa535878b55cfc.png


全部入栈:

02a863de52b8d53633074eabd5ebcd44.png

因为栈是先进后出的数据结构,因此它的执行过程如下图所示:

dd1ea0c891f08660c91792ab7feca996.png

a4c50225bafdf260a25279e23ecb842f.png

22d11e6bcb2a1b39204a5f3378d0237e.png

最终的执行结果如下图所示:

999f7154982255fc5301477f03e58a9f.png

实现代码如下所示:

public ListNode reverseList(ListNode head) {
    if (head == null) return null;
    Stack stack = new Stack<>();
    stack.push(head); // 存入第一个节点while (head.next != null) {
        stack.push(head.next); // 存入其他节点
        head = head.next; // 指针移动的下一位
    }// 反转链表
    ListNode listNode = stack.pop(); // 反转第一个元素
    ListNode lastNode = listNode; // 临时节点,在下面的 while 中记录上一个节点while (!stack.isEmpty()) {
        ListNode item = stack.pop(); // 当前节点
        lastNode.next = item;
        lastNode = item;
    }
    lastNode.next = null; // 最后一个节点赋为null(不然会造成死循环)return listNode;
}

LeetCode 验证结果如下图所示:

004d232779edaba2a28861889698d49d.png

实现方式二:递归

b74089d99cda3604e038d58e1f798536.png

37801978259e32352397d06c9980edcb.png

f76fee3f710d1568ef1722efcc6e3797.png

4e8f19b03f67eade82c6fd3d0116ad6c.png

e5a9be87119ab5aa5c053d6727cdb070.png

实现代码如下所示:

public static ListNode reverseList(ListNode head) {
    if (head == null || head.next == null) return head;
    // 从下一个节点开始递归
    ListNode reverse = reverseList(head.next);
    head.next.next = head; // 设置下一个节点的 next 为当前节点
    head.next = null; // 把当前节点的 next 赋值为 null,避免循环引用
    return reverse;
}

LeetCode 验证结果如下图所示:

7fd23779643f7908f14c37742d28264e.png

总结

本文我们分别使用了 Stack 和递归的方法实现了链表反转的功能,其中 Stack 的实现方式是利用了栈后进先出的特性可以直接对链表进行反转,实现思路和实现代码都比较简单,但在性能和内存消耗方面都不是很理想,可以作为笔试的保底实现方案;而递归的方式在性能和内存消耗方面都有良好的表现,同时它的实现代码也很简洁,读者只需理解代码实现的思路即可。

f589aac6e2a1fbba2c5979b7ccbb3935.gif

往期推荐

a2f663b2c09eaff88a6cf3bd339eecbe.png

JDK 竟然是这样实现栈的?

9999d8e91fd0d0fbff028f8dad018631.png

动图演示:手撸堆栈的两种实现方法!

da91e28ce72a3e783fb8b785d429b5f1.png

漫画:什么是红黑树?(整合版)

关注下方二维码,收获更多干货!

b411771047167c135f2c9a02e1b171ff.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值