两个链表的入环节点(java)

news2024/11/15 9:28:25

两个链表的入环节点

  • 两个链表的入环节点
    • 解题思路
    • 代码演示
  • 链表相关的题

两个链表的入环节点

给定两个可能有环也可能无环的单链表,头节点head1和head2 请实现一个函数,如果两个链表相交,请返回相交的第一个节点。如果不相交返回null 要求如果两个链表长度之和为N,时间复杂度请达到O(N),额外空间复杂度请达到O(1)

解题思路

这个问题,是链表中比较难的问题,我们要分成几步去思考,
首先如何判断一个链表有环无环,
这个可以用快慢指针的方式去处理,
快指针一次走两步。慢指针一次走一步,如果链表无环,快指针会率先走到结尾,也就是null;
如果有环,快指针会在环内一直循环,慢指针进环后,总会有时机和快指针相遇,根据这个情况,我们可以先判断两个链表有环无环。

找入环节点还有个技巧,当快指针和慢指针相遇后,快指针回到头节点,然后改成每次走一步,慢指针还继续每次走一步,然后再次相遇就是入环节点,可以自己证明下。

判断有环无环后,如何判断两个链表是否相交的。
这时就要讨论几种情况。如图演示
在这里插入图片描述

只有这三种情况,第一个两个入环节点,
第二种,一个入环节点,
第三种l两个链表都没有环
注意:不存在一个有环一个无环还能相交的情况,因为是单链表,
分别讨论以上几种情况,去计算入环节点。
第一种情况呢,两个入环节点,随便返回其中一个就可以,
第二种要找到入环节点后向前推,去找到相交的点,
第三种情况,直接找出入环节点,这个技巧在代码里讲述把

代码演示

1.先定义一个链表结构

    public static class Node{
        private int val;
        private Node next;

        public Node(int val) {
            this.val = val;
        }
    }
  1. 判断一个链表是否有环,并返回入环节点
  /**
     * 如果一个链表有环 返回第一个入环节点,没环返回null
     *
     * @param head
     * @return
     */
    public static Node findLoop(Node head){
        //无环 直接返回null
        if (head == null || head.next == null || head.next.next == null){
            return null;
        }

        Node slow = head.next;
        Node fast = head.next.next;
        //一个结论 如果有环的话 必会在环节点的某处位置相交.
        while (slow != fast){
            //有环的链表 不会走向null 如果有null 代表是无环链表
            if (slow.next == null || fast.next.next == null){
                return null;
            }
            slow = slow.next;
            fast = fast.next.next;
        }
        //现在fast 和 slow 是相同 此时把fast放到头节点
        //此时快慢节点保持相同的速度 ,就会在入环节点相交.
        fast = head;
        while (fast != slow){
            slow = slow.next;
            fast = fast.next;
        }
        return slow;

    }

3.两个都无环时,找出相交点

   /**
     * 如果两个链表都是无环的.那么此时查找第一个相交的节点
     * 如果相交,就像图种演示的一样,一定最后非空节点是相等的,
     * @param head1
     * @param head2
     * @return
     */
    public static Node noLoop(Node head1,Node head2){
        //先证明是否相交
        Node cur1 = head1;
        Node cur2 = head2;
        int n  = 0; //链表长度
        //来到最后节点并计算长度
        while (cur1 != null){
            n++;
            cur1 = cur1.next;
        }
        //head2 也来到最后节点 并且计算两个链表的长度差
        while (cur2 != null){
            n--;
            cur2 = cur2.next;
        }
        //如果相交 最后一个节点肯定相同的.首先判断下是否相同
        if (cur1 != cur2){
            //不等 代表没有相交 返回null;
            return null;
        }

        //cur1 代表长链表 cur2 代表短链表
        cur1 = n > 0 ? head1 : head2;
        cur2 = cur1 == head1 ? head2 : head1;
        n = Math.abs(n);
        //如果相交,相交后的部分是等长的,差值就在相交前的部分,
        //上面分析出长链表后,先走长度的差值部分,然后剩余到相交节点的长度就是一样了,
        //然后同时走,相遇就是相交节点了
        while (n != 0){
            n--;
            cur1 = cur1.next;
        }
        while (cur1 != cur2){
            cur1 = cur1.next;
            cur2 = cur2.next;
        }
        return cur1;
    }

  1. 都有环时
    /**
     * 都有环 也分两种情况 只有一个入环节点,和有两个入环节点
     * @param head1
     * @param head2
     * @return
     */
    public static Node bothLoop(Node head1,Node head2,Node loop1,Node loop2){
        //x先把入环节点找出来
        Node cur1 = head1;
        Node cur2 = head2;
        //入环节点相等 时,找出相交节点
        //从环节点以上看,类似第一种情况都无环的求交点的方式,代码也一样.
       if (loop1 == loop2){
           //肯定相交
           int n = 0;
           while (cur1 != loop1){
               n++;
               cur1 = cur1.next;
           }
           while (cur2 != loop2){
               n-- ;
               cur2 = cur2.next;
           }
           cur1 = n > 0 ? head1 : head2;
           cur2 = cur1 == head1 ? head2 : head1;
           n = Math.abs(n);
           while (n != 0 ){
               n--;
               cur1 = cur1.next;
           }
           while (cur1 != cur2){
               cur1 = cur1.next;
               cur2 = cur2.next;
           }

           return  cur1;
       }else{
           //有可能相交 也有可能不相交
           //在换上转圈 如果能遇到loop2 就是相交,遇不到 就是不相交
           cur1 = loop1.next;
           while (cur1 != loop1){
               if (cur1 == loop2){
                   return cur1;
               }
               cur1 = cur1.next;
           }
           return null;
       }
    }

5,方法组合起来就是最终答案

 /**
     * 相交节点
     * @param head1
     * @param head2
     * @return
     */
    public static Node findIntersectNode(Node head1,Node head2){
        //head1 的入环节点
        Node loop1 = findLoop(head1);
        //head2 的入环节点
        Node loop2 = findLoop(head2);
        //无环时
        if (loop1 == null && loop2 == null){
            return noLoop(head1,head2);
        }
        //都有环时
        if (loop1 != null && loop2 != null){
            return bothLoop(head1,head2,loop1,loop2);
        }
        return null;
    }

链表相关的题

leetcode 二叉树展开为链表

递归实现翻转链表

删除排序链表中的重复元素

leetcode143. 重排链表

leetcode109. 有序链表转换二叉搜索树

leetcode61. 旋转链表

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/693350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ATTCK(一)之为什么要学习ATTCK

ATT&CK 简介 本系列旨在介绍网络红蓝对抗领域最好的ATT&CK矩阵模型,以期帮助有意愿深耕在红蓝对抗领域的人员能系统性的掌握红蓝对抗领域的知识和经验。本系列将详细ATT&CK的起源、发展历史,ATT&CK矩阵相对其他High-Level红蓝对抗模型…

Redis7【② Key通用命令 十大数据类型】

1 Key的通用命令 redis命令不区分大小写,但是key是区分大小写的。没有返回值的命令执行成功会返回1,失败返回0。 1. KEYS 查看所有的key,返回值是一个数组 2. EXISTS EXISTS key [key ...]:返回给定的key中已存在的个数&#xf…

前端Vue自定义验证码密码登录切换tabs选项卡标签栏标题栏 验证码登录模版 密码登录模版

前端Vue自定义验证码密码登录切换tabs选项卡标签栏标题栏 验证码登录模版 密码登录模版, 请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id13221 效果图如下: 实现代码如下: # cc-selectBox #### 使用方法 使…

【计算机网络】可靠传输的实现机制

1、停止-等待协议SW 信道利用率 题目 小结 2.回退N帧协议GBN Go-Back-N 题目 小结

设计模式3:单例模式:JMM与volatile和synchronized的关系

本文目录 JMM简介Java 内部内存模型(The Internal Java Memory Model)硬件内存架构(Hardware Memory Architecture)弥合 Java 内存模型和硬件内存架构之间的差距(Bridging The Gap Between The Java Memory Model And The Hardware Memory Architecture)1.共享对象的可见性2.竞…

OpenStack(T版)——计算(Nova)服务介绍与安装

文章目录 OpenStack(T版)——计算(Nova)服务介绍与安装安装与配置(controller)准备(1)创建数据库(2)加载环境变量(3)创建认证服务凭据(4)创建Nova计算服务组件的API endpoint 安装和配置Nova计算服务组件(1)安装软件包(2)编辑/etc/nova/nova.conf 完成以下操作(3)同步数据库验证…

云服务器Linux防火墙云锁安装部署及使用 技术支持服务器安全运维

服务器必备安全防护及运维管理SAAS解决方案,支持windows/linux服务器跨平台实时、批量、远程安全管理,有效对抗服务器入侵和网络攻击。 服务器:Redhat/CentOS/Ubuntu/SUSE/中标麒麟 64位 Web中间件:Apache/Nginx/kangle/Tomcat/W…

【软考网络管理员】2023年软考网管初级常见知识考点(26)- HTML常见属性标签、表格、表单详解

涉及知识点 Html的概念,html常见标签,html常见属性,html表格,html表单,软考网络管理员常考知识点,软考网络管理员网络安全,网络管理员考点汇总。 原创于:CSDN博主-《拄杖盲学轻声码…

5-2图像处理经典案例:正弦噪声图像去噪

学习目标: 图像处理经典案例 去除噪声 1.简述 图像降噪的英文名称是Image Denoising, 图像处理中的专业术语。是指减少数字图像中噪声的过程,有时候又称为图像去噪。图像的噪声来源相对复杂,搞清楚图像噪声的成因对我们进行…

B+树

B树 B树是对B树的一种变形树,它与B树的差异在于: 非叶结点仅具有索引作用,也就是说,非叶子结点只存储key,不存储value 树的所有叶结点构成一个有序链表,可以按照key排序的次序遍历全部数据 B树存储数据 若参数M选…

使用影刀RPA拆分excel数据

首先,要使程序有一定的兼容性,即增加互动性,认为选择要拆分的文件和拆分的依据列,可以利用影刀中的‘打开选择对话框’和‘打开输入对话框’来实现,这样一来便不用考虑待拆分excel的路径问题获取1中选择的依据拆分列&a…

登录框界面之渗透测试思路总结

前言 大家都知道,渗透的过程中,遇见登录框是很常见的。下面就简单总结一下渗透中遇见登录页面的思路: 首先登录页面可能产生哪些漏洞呢? 1、弱密码与暴力破解 2、万能密码、SQL与XSS(注入) 3、登录时&…

渗透测试自动化报告脚本-----Nessus报告自动化解析--1-html解析

本专栏内容主要用于渗透测试工程师应对在工作中的自动化操作难题,高效摸鱼专用 解决问题 1、对Nessus导出的html报告进行自动化的提取操作,包括IP地址,漏洞个数,漏洞等级,漏洞描述,CVE编号等 2、由于Nes…

配置文件的优先级及maven打包和参数(port)的修改

1、配置文件的优先级 SpringBoot中支持五种配置格式:优先级:命令行参数(–xxxxxx) > java系统属性(-Dxxx xxx) > application.properties > application.yml > application.yaml 虽然springboot支持多种格式配置文件,但是在项目开发时&…

智能仓储货架的电子标签解决方案

近年来,电商和新零售行业的迅猛增长催生了仓储管理场景和运营模式的变革。企业不断寻求“低成本”和“更可靠”的解决方案,加快了仓储管理从粗放型向精细化转变的步伐。仓储管理的技术变革从机械化走向自动化,仓储数智化成为主流趋势。在这个…

chatgpt赋能python:Python语言冒泡排序-深入了解

Python语言冒泡排序 - 深入了解 冒泡排序是一种基本的排序算法,也是学习排序算法的入门算法之一。在Python中,我们可以很容易地实现冒泡排序。 冒泡排序的原理 冒泡排序的原理很简单,大概分为以下几个步骤: 比较相邻的元素&am…

Jnpf低代码开发平台

一、写在前面 低代码开发平台,一个号称能在几分钟的时间里开发出一套公司内部都可使用的应用系统开发工具。 很多人或许都隐隐听说过低代码,因为低代码不仅远名国外,国内的腾讯、阿里、华为、网易、百度等科技巨头也纷纷入局,足以…

蓝桥杯专题-试题版-【打印十字图】【剪格子】【错误票据】【翻硬币】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…

【软考网络管理员】2023年软考网管初级常见知识考点(29)-进程管理与存储管理

涉及知识点 进程管理,进程状态,死锁问题,存储管理,页面置换算法,软考网络管理员常考知识点,软考网络管理员网络安全,网络管理员考点汇总。 原创于:CSDN博主-《拄杖盲学轻声码》&…

高速电路设计系列分享-熟悉JESD204B(中)

目录 概要 整体架构流程 技术名词解释 技术细节 1.数据链路层 小结 概要 提示:这里可以添加技术概要 随着高速ADC跨入GSPS范围,与FPGA(定制ASIC)进行数据传输的首选接口协JESD204B。为了捕捉频率范围更高的RF频谱,需要宽带RFADC。在其推动下…