两个单链表相交的问题

news2024/10/5 18:36:50

两链表相交及其第一个节点 

 

判断有环无环

判断有无环,如果有环返回第一个入环节点,如果无环返回null

使用额外空间:Set结构

沿着指针将a、b、c、d、e、c放入set结构中,每次放入前查看在set集合中是否存在;

若遍历到null都没有重复节点,那么链表为无环链表;

若有重复,链表有环,第一个重复的值即为第一个入环节点

不使用额外空间

如果一个链表无环,一定能够指向null

如果一个链表有环,最终它一定在一直循环

快慢指针:快指针一次走两步,慢指针一次走一步

如果一个链表无环,快指针先指向null

如果一个链表有环,快满指针一定会在某一时刻相遇

(不一定在入环节点相遇并且慢指针在环中转的圈数不超过两圈

相遇之后,慢指针在原地,快指针回到起点,接下来快慢指针都走一步,两个指针一定会在入环节点相遇(数学证明)

//判断有环无环,有环返回第一个入环节点,无环返回null
    public static Node getloopNode(Node head) {

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

        //快慢指针相遇的时候停止,如果快慢指针都从head出发,开始时相遇,所以快指针先走两步,慢指针走一步
        Node slow = head.next;
        Node fast = head.next.next;
        while (slow != fast) {
            if (fast.next == null || fast.next.next == null) {//无环
                return null;
            }

            slow = slow.next;
            fast = fast.next.next;
        }

        fast = head;//回到开头
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }

        return slow;
    }

对两个链表分类讨论

两个链表分别调用getloopNode方法

两个无环单链表

        loop1 == null        loop2 == null

        不可能如左图所示,单链表只能有一个next指针;如果两链表相交,一定是右图所示

                     

      先遍历两个链表,记录两链表的长度;

      比较链表最后一个Node,如果相等,则两链表相交;若不相等,则两链表不相交

      长链表先走两个链表之间的长度差,之后两链表再一起走,两链表在第一个相交节点处相遇  

//如果两个链表都无环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    public static Node noLoop(Node head1, Node head2) {
        if (head1 == null || head2 == null) {
            return null;
        }

        int length1 = 0, length2 = 0;
        //遍历链表1
        while (head1.next != null) {//链表1在最后一个节点停
            length1++;
            head1 = head1.next;
        }
        //遍历链表2
        while (head2.next != null) {//链表2在最后一个节点停
            length2++;
            head2 = head2.next;
        }

        if (head1 == head2) {//不相交
            return null;
        } else {
            while(head1 != head2){//还没相遇
                if (length1 > length2) {//链表1较长
                    length1--;
                    head1 = head1.next;
                    
                } else if (length1 < length2) {//链表2较长
                    length2--;
                    head2 = head2.next;

                } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                    head1 = head1.next;
                    head2 = head2.next;
                }
            }
        }
        
        return head1;
    }

一个有环单链表,一个无环单链表 

此种情况两链表不可能相交,一定会有某个节点有两个next指针

两个有环单链表

                                                      

情况2:求相交节点 = 两无环单链表求相交节点

             把入环节点看成结尾,终止节点为loop1==loop2

情况1和情况3:loop1继续向下走,如果在循环中没有遇到loop2,则两链表不相交;

                         如果在循环的过程中遇到了loop2,则两链表相交

                         返回的结果既可以是loop1,也可以是loop2,两个节点都是两链表的相交节点

//如果两个链表都有环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    //loop1 = getloopNode(head1);   loop2 = getloopNode(head2);
    public static Node bothLoop(Node head1, Node head2, Node loop1, Node loop2) {

        if (loop1 == loop2) {//情况2

            int length1 = 0, length2 = 0;
            //遍历链表1
            while (head1.next != null) {//链表1在最后一个节点停
                length1++;
                head1 = head1.next;
            }
            //遍历链表2
            while (head2.next != null) {//链表2在最后一个节点停
                length2++;
                head2 = head2.next;
            }

            if (head1 == head2) {//不相交
                return null;
            } else {
                while (head1 != head2) {//还没相遇
                    if (length1 > length2) {//链表1较长
                        length1--;
                        head1 = head1.next;

                    } else if (length1 < length2) {//链表2较长
                        length2--;
                        head2 = head2.next;

                    } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                        head1 = head1.next;
                        head2 = head2.next;
                    }
                }
            }
            return head1;

        } else {//情况1和情况3

            Node temp = loop1.next;
            while (temp != loop1) {//在圈里面遍历

                if (temp == loop2) {//遇到loop2,情况3
                    return loop1;//return loop2;
                }
                temp = temp.next;
            }

            return null;//情况1
        }
    }

回到题目

调用 

public static Node getIntersectNode(Node head1,Node head2){
        if(head1 == null || head2 == null){
            return null;
        }

        Node loop1 = getloopNode(head1);
        Node loop2 = getloopNode(head2);
        if(loop1 == null && loop2 == null){
            return noLoop(head1,head2);
        } else if (loop1 != null && loop2 != null) {
            return bothLoop(head1,head2,loop1,loop2);
        }else{
            return null;
        }
    }

 全代码

package linkedlist;

public class IntersectLinkedList {
    class Node {
        public int value;
        public Node next;

        public Node(int data) {
            this.value = data;
        }

    }

    //判断有环无环,有环返回第一个入环节点,无环返回null
    public static Node getloopNode(Node head) {

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

        //快慢指针相遇的时候停止,如果快慢指针都从head出发,开始时相遇,所以快指针先走两步,慢指针走一步
        Node slow = head.next;
        Node fast = head.next.next;
        while (slow != fast) {
            if (fast.next == null || fast.next.next == null) {//无环
                return null;
            }

            slow = slow.next;
            fast = fast.next.next;
        }

        fast = head;//回到开头
        while (slow != fast) {
            slow = slow.next;
            fast = fast.next;
        }

        return slow;
    }


    //如果两个链表都无环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    public static Node noLoop(Node head1, Node head2) {
        if (head1 == null || head2 == null) {
            return null;
        }

        int length1 = 0, length2 = 0;
        //遍历链表1
        while (head1.next != null) {//链表1在最后一个节点停
            length1++;
            head1 = head1.next;
        }
        //遍历链表2
        while (head2.next != null) {//链表2在最后一个节点停
            length2++;
            head2 = head2.next;
        }

        if (head1 == head2) {//不相交
            return null;
        } else {
            while (head1 != head2) {//还没相遇
                if (length1 > length2) {//链表1较长
                    length1--;
                    head1 = head1.next;

                } else if (length1 < length2) {//链表2较长
                    length2--;
                    head2 = head2.next;

                } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                    head1 = head1.next;
                    head2 = head2.next;
                }
            }
        }

        return head1;
    }


    //如果两个链表都有环,判断两链表是否相交,相交则返回第一个相交节点,不相交则返回null
    //loop1 = getloopNode(head1);   loop2 = getloopNode(head2);
    public static Node bothLoop(Node head1, Node head2, Node loop1, Node loop2) {

        if (loop1 == loop2) {//情况2

            int length1 = 0, length2 = 0;
            //遍历链表1
            while (head1.next != null) {//链表1在最后一个节点停
                length1++;
                head1 = head1.next;
            }
            //遍历链表2
            while (head2.next != null) {//链表2在最后一个节点停
                length2++;
                head2 = head2.next;
            }

            if (head1 == head2) {//不相交
                return null;
            } else {
                while (head1 != head2) {//还没相遇
                    if (length1 > length2) {//链表1较长
                        length1--;
                        head1 = head1.next;

                    } else if (length1 < length2) {//链表2较长
                        length2--;
                        head2 = head2.next;

                    } else {//长链表先走了差值长度之后,两链表一起走直到相遇
                        head1 = head1.next;
                        head2 = head2.next;
                    }
                }
            }
            return head1;

        } else {//情况1和情况3

            Node temp = loop1.next;
            while (temp != loop1) {//在圈里面遍历

                if (temp == loop2) {//遇到loop2,情况3
                    return loop1;//return loop2;
                }
                temp = temp.next;
            }
        }
        return null;//情况1
    }

    public static Node getIntersectNode(Node head1,Node head2){
        if(head1 == null || head2 == null){
            return null;
        }

        Node loop1 = getloopNode(head1);
        Node loop2 = getloopNode(head2);
        if(loop1 == null && loop2 == null){
            return noLoop(head1,head2);
        } else if (loop1 != null && loop2 != null) {
            return bothLoop(head1,head2,loop1,loop2);
        }else{
            return null;
        }
    }
    

}




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

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

相关文章

供应商整合对企业有哪些好处?

企业采购总是希望降低成本&#xff0c;赢得更多的利润。实现这目标的其中一种方法就是供应商整合。 究竟什么是供应商整合&#xff1f;整合供应商有哪些好处&#xff1f;本文为你详细解答。 什么是供应商整合&#xff1f; 供应商整合是减少特定产品或服务的供应商数量的过程。…

JTS:06 九交模型讲解

版本 org.locationtech.jts:jts-core:1.19.0 链接: github 九交模型讲解&#xff1a;Dimensionally Extended 9 Intersection Matrix 九交模型 九交模型&#xff0c;是通过矩阵来判断俩个物体的关系的&#xff0c;请看上面九交模型讲解 九交模型测试 测试环境 www.geogebra…

Unity中 UI Shader的基本功能

文章目录 前言一、实现思路1、暴露一个 2D 类型的属性来接受UI的纹理2、设置shader的层级为TransParent半透明渲染层级&#xff0c;一般UI都是在这个渲染层级3、更改混合模式&#xff0c;是 UI 使用的纹理&#xff0c;该透明的地方透明 二、代码实现 前言 Unity中 UI Shader的…

SpringBoot-线程池ThreadPoolExecutor异步处理(包含拆分集合工具类)

ThreadPoolExecutor VS ThreadPoolTaskExecutor ThreadPoolTaskExecutor是对ThreadPoolExecutor进行了封装处理。 配置文件application.yml # 异步线程配置 自定义使用参数 async:executor:thread:core_pool_size: 10max_pool_size: 100 # 配置最大线程数queue_capacity: …

gif动态图片如何做?两个方法教你在线制作gif

制作gif动画的方法有哪些&#xff1f;gif动图作为当下流行的一种图片格式&#xff0c;是由一帧一帧的图像&#xff0c;循环播放而产生的动画效果。那么&#xff0c;制作gif动画的方法有哪些呢&#xff1f;给大家分享一款专业的gif动画制作&#xff08;https://www.gif.cn/&…

【JVM】Java的内存模型(JMM)!

一、运行时数据区域划分 JVM虚拟机在执行 Java 程序的过程中会把它管理的内存划分成若干个不同的数据区域。 JDK 1.8之前分为&#xff1a;线程共享&#xff08;Heap堆区、Method Area方法区&#xff09;、线程私有&#xff08;虚拟机栈、本地方法栈、程序计数器&#xff09; …

“一种三元前驱体废水螯合树脂回收钴的装置”实用新型专利

“一种三元前驱体废水螯合树脂回收钴的装置”实用新型专利 (证书号&#xff1a;第19681862号;专利号&#xff1a;ZL 2022 2 1042752.0) 三元前驱体通常由三元液(硫酸镍、钴、锰的混合溶液)、液碱与氨水在一定条件下液相合成&#xff0c;再经陈化、固液分离、流水洗涤、干燥、过…

PMP考试注意事项有哪些?

1. PMI明确规定&#xff1a;不允许考生使用自带文具&#xff0c;包括自带的笔、削笔刀、橡皮、笔袋、计算器和草稿纸等。 2. 本次考试考场内为每位考生配备2B铅笔、橡皮、计算器(若有需要)和草稿纸。如文具有缺损或考试过程中如需更换铅芯等&#xff0c;请向监考老师举手示意。…

【实战】H5 页面同时适配 PC 移动端 —— 旋转横屏

文章目录 一、场景二、方案三、书单推荐01 《深入实践Kotlin元编程》02 《Spring Boot学习指南》03 《Kotlin编程实战》 一、场景 一个做数据监控的单页面&#xff0c;页面主要内容是一个整体必须是宽屏才能正常展示&#xff0c;这时就不能用传统的适配方案了&#xff0c;需要…

DC电源模块单路、双路输出的不同应用场景

BOSHIDA DC电源模块单路、双路输出的不同应用场景 DC电源模块是一种常见的供电设备&#xff0c;通常用于将市电转换为稳定的直流电源&#xff0c;以供电给各种电子设备。DC电源模块的输出方式分为单路和双路两种&#xff0c;下面将分别介绍它们的不同应用场景。 一、单路输出…

wx.getPrivacySetting 小程序隐私保护指引的使用(复制粘贴即用)

创建privacyPopup 组件 privacyPopup.js Component({properties: {},data: {wxPrivacyName: ,showAgreement: false},lifetimes: {attached() {this.init();}},methods: {async init() {if (isLogin()) {const userPrivacy await this.getPrivacy();this.setData({wxPrivacy…

vue项目生产环境隐藏暴露的代码_源码

// 如果你不需要生产环境的 source map&#xff0c;可以将其设置为 false 以加速生产环境构建。 productionSourceMap: false,

思维导图,掌握思维的艺术!免费的Mindomo Desktop for Mac等你来体验

您是否曾为了整理复杂的思绪而苦恼&#xff1f;或许您需要一款强大而直观的思维导图软件来帮助您理清思路。Mindomo Desktop for Mac是一款免费的思维导图软件&#xff0c;它将为您带来高效的思考和组织工具。 Mindomo Desktop for Mac的界面简洁直观&#xff0c;操作简单易上…

留资机器人助你有效提高营销成功率

我们都知道&#xff0c;当客户产生留资行为&#xff0c;就要抓住机会&#xff0c;让工作人员及时地对客户进行回访&#xff0c;然后将留资线索跟踪、维系。而如何准确有效地提高客户保留率和转化率是营销成功的关键。所以对于企业来说&#xff0c;留资机器人正是引导客户留资&a…

自动化测试工程师简历(吐血整理)附模板

张三&#xff08;软件测试&#xff09; 联系电话&#xff1a;175XXXXXXXXX 电子邮件&#xff1a;XXXqq.com 学 历&#xff1a;本 科 专 业&#xff1a;计算机科学与技术 毕业院校&#xff1a;XXXXXX …

Redis缓存高可用集群

1、Redis集群方案比较 哨兵模式 在redis3.0以前的版本要实现集群一般是借助哨兵sentinel工具来监控master节点的状态&#xff0c;如果master节点异常&#xff0c;则会做主从切换&#xff0c;将某一台slave作为master&#xff0c;哨兵的配置略微复杂&#xff0c;并且性能和高可…

Postman应用——接口请求(Get和Post请求)

文章目录 新增请求接口请求Get接口请求Post 这里只讲用的比较多的Get和Post请求方式&#xff0c;也可以遵循restful api接口规范&#xff0c;使用其他请求方式。 GET&#xff08;SELECT&#xff09;&#xff1a;从服务器取出资源&#xff08;一项或多项&#xff09;POST&#…

建筑模板的成本如何控制?

建筑模板是在施工过程中用于支撑混凝土浇筑的临时结构&#xff0c;对于建筑项目而言&#xff0c;模板的成本控制是一个重要的方面。有效地控制模板成本可以帮助降低整体工程成本&#xff0c;并提高项目的经济效益。本文将从不同网站链接的内容中总结出一些关键要点&#xff0c;…

2023华为OD统一考试(B卷)题库清单(按算法分类),如果你时间紧迫,就按这个刷

目录 专栏导读华为OD机试算法题太多了&#xff0c;知识点繁杂&#xff0c;如何刷题更有效率呢&#xff1f; 一、逻辑分析二、数据结构1、线性表① 数组② 双指针 2、map与list3、优先队列4、滑动窗口5、二叉树6、并查集7、栈 三、算法1、基础算法① 贪心算法② 二分查找③ 分治…

HTML5+CSS3小实例:纯CSS实现彩虹倒映水面的唯美背景

实例:纯CSS实现彩虹倒映水面的唯美背景 技术栈:HTML+CSS 效果: 源码: 【html】 <!DOCTYPE html> <html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"><meta name="viewport" …