当前位置: 首页 > news >正文

链表中环的入口节点 -- java

题目描述

如果一个链表中包含环,如何找出环的入口节点?例如,在如下图所示的链表中,环的入口节点是节点3。

在这里插入图片描述

解题思路

  1. 确定一个链表中包含环
    用两个指针指向头节点指针,同时从链表的头节点触发,一个指针一次走一步,另一个指针一次走两步。如果走得快的指针追上了走得慢的指针,那么链表就包含环,如果的走得快的指针走到了链表的末尾都没有追上走得慢的指针,那么链表就不包含环。

  2. 找到环的入口
    用两个指向头节点的指针P1,P2,如果链表中的环有n个节点,则一个指针P1指针先向前移动n步,然后两个指针以相同的速度向前移动。当P2指向指向环的入口节点时,P1已经围绕环走了一圈,又回到了入口节点。

找到环的入口这里的双指针移动可以这么理解:假如链表像图片那样链表一共有6个节点,环中有4个节点,那么不在环中的节点就是6-4=2,环的入口就知道了,是3。所以也可以不用双指针的方式,让头指针移动2步就可以到达环的入口。

对使用双指针方式的理解:环中有4个节点,先让一个节点P1移动4步,那么节点总数6-移动步数4=2,2=P1再移动2步就到入口=P2从头部移动2步到入口。

  1. 得到环中节点的数目
    我们在前面提到判断一个链表是否有环时用到了一快一慢两个指针。如果两个指针相遇,则表明链表中存在环。两个指针相遇的节点一定在环中,可以从这个节点出发,一边继续向前移动一边计数,当再次回到这个节点时,就可以得到环中节点数了。

代码

ListNode类定义:

public class ListNode {
    int value;
    ListNode next = null;

    public ListNode() {
    }

    public ListNode(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "ListNode{" +
                "value=" + value +
                '}';
    }
}

EntryNodeOfLoop类:

public class EntryNodeOfLoop {

    public static ListNode entryNodeOfLoop(ListNode head) {
        ListNode meetingNode = meetingNode(head);
        if (meetingNode == null) {
            return null;
        }

        // 得到环中节点的数目
        int nodesInLoop = 1;
        ListNode p1 = meetingNode;
        while (p1.next != meetingNode) {
            p1 = p1.next;
            nodesInLoop++;
        }

        // 先移动p1,次数为环中节点的数目
        p1 = head;
        for(int i = 0; i < nodesInLoop; i++) {
            p1 = p1.next;
        }

        // 再移动p1和p2
        ListNode p2 = head;
        while (p1 != p2) {
            p1 = p1.next;
            p2 = p2.next;
        }

        return p1;
    }

    /**
     * 在链表中存在环的前提下找到一快一慢两个指针相遇的节点
     * @param head 头节点
     * @return 返回相遇的节点,如果不存在环那么返回null
     */
    public static ListNode meetingNode(ListNode head) {
        if (head == null) {
            return null;
        }

        ListNode slow = head.next;
        if (slow == null) {
            return null;
        }

        ListNode fast = slow.next;
        while (fast != null && slow != null) {
            // 相遇
            if (fast == slow) {
                return fast;
            }

            slow = slow.next;
            fast = fast.next;
            if (fast != null) {
                fast = fast.next;
            }
        }

        return null;
    }

    // 测试
    public static void main(String[] args) {
        ListNode node1 = new ListNode(1);
        ListNode node2 = new ListNode(2);
        ListNode node3 = new ListNode(3);
        ListNode node4 = new ListNode(4);
        ListNode node5 = new ListNode(5);
        ListNode node6 = new ListNode(6);

        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        // 环
        node6.next = node3;

        System.out.println(meetingNode(node1));
    }
}


来自:

《剑指Offer》
Coding-Interviews/链表中环的入口节点.md at master · todorex/Coding-Interviews

相关文章:

  • 反转链表 -- java
  • 合并两个排序的链表 -- java
  • Mac上使用宁芝普拉姆键盘的记录
  • idea Mac格式化代码快捷键
  • 搜狗输入法关闭候选词中的图标只显示文字
  • Mac关闭idea的双击shift全局搜索功能
  • 树的子结构 -- java
  • 二叉树的镜像 -- java
  • java 遍历二叉树使用循环方式
  • 隐藏csdn博客的标题X条消息的方式
  • 对称的二叉树 -- java
  • 顺时针打印矩阵 -- java
  • 包含min函数的栈 -- java
  • 栈的压入、弹出序列 -- java
  • windows 远程桌面连接(mstsc)删除下拉框的记录
  • @angular/forms 源码解析之双向绑定
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • Fabric架构演变之路
  • Laravel 中的一个后期静态绑定
  • learning koa2.x
  • leetcode388. Longest Absolute File Path
  • Linux快速复制或删除大量小文件
  • magento2项目上线注意事项
  • mysql_config not found
  • Python实现BT种子转化为磁力链接【实战】
  • Sequelize 中文文档 v4 - Getting started - 入门
  • SQLServer之创建数据库快照
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 欢迎参加第二届中国游戏开发者大会
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 力扣(LeetCode)22
  • 如何设计一个微型分布式架构?
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 王永庆:技术创新改变教育未来
  • 学习ES6 变量的解构赋值
  • 用element的upload组件实现多图片上传和压缩
  • ​用户画像从0到100的构建思路
  • (pojstep1.1.2)2654(直叙式模拟)
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (四)linux文件内容查看
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .NET Core 2.1路线图
  • .NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .Net接口调试与案例
  • .net项目IIS、VS 附加进程调试
  • .NET中使用Redis (二)
  • /usr/bin/env: node: No such file or directory
  • @Pointcut 使用
  • @SentinelResource详解
  • [ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现