• LeetCode每日一练 —— 160. 相交链表


    🌟 前言

    Wassup guys!我是Edison 😎

    今天是 LeetCode 上的 leetcode 160. 相交链表

    Let’s get it!

    在这里插入图片描述



    1. 题目分析

    给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
     
    图示两个链表在节点 c1 开始相交:
    在这里插入图片描述
    题目数据 保证 整个链式结构中不存在环。
     
    注意,函数返回结果后,链表必须 保持其原始结构

    示例 1:
    在这里插入图片描述

    示例 2:
    在这里插入图片描述

    示例 3:
    在这里插入图片描述

    2. 思路分析

    这道题拆分的话,其实就是两步:

    (1)判断两个链表是否相交
     
    (2)然后找出第一个交点

    🍑 判断相交

    首先要判断链表 A 和 链表 B 是否相交,那怎么判断呢?

    1. 思路一

    就是用 链表 A 的每一个节点去和 链表 B 依次比较判断,如果有相等,就是相交,第一个相等就是相交;反之,不相交
     
    但是这种方法需要那 A 里面的每一个节点去和 B 里面的 N 个节点进行比较,如果 AM 个节点,那么时间复杂度就是 O ( M ∗ N ) O(M*N) O(MN)
     
    注意:这里比较的不是节点里面的 ,比较的是 当前节点存放的下一个节点的地址

    2. 思路二

    A链表 找到 尾节点B链表 也找到 尾节点
     
    尾节点 的地址相同时,就是 相交
     
    这种方法的时间复杂度为: O ( M + N ) O(M+N) O(M+N)

    🍑 求出交点

    既然能判断链表是否相交了,那么如何找到交点呢?

    也很简单,直接说方法:

    (1)求出 A链表 的长度 La,再求出 B链表 的长度 Lb
     
    (2)如果 A链表B链表 长,那么 A链表 先走 La - Lb 步;
     
    (2)当 A链表 走了 差距步 以后,再让 A链表B链表 再一起走,第一个 地址 相等的就是交点。

    注意:

    如果 B链表A链表 长,那么让 B链表 先走 Lb - La 步;
     
    为什么要用 长的 减去 短的?因为这样得到的结果才是一个 正数 呀,这两个相减得到的值就是 差距步
     
    其实这道题有点和 链表中倒数第 k 个结点 相似。

    🍑 实现步骤

    既然判断相交要从 头节点 开始走到 尾节点,那么我们就重新定义两个指针 tailAtailB 分别指向 链表A链表B 的头节点,然后开始往后走;

    tailA 先走,当 tailA 走到 尾节点 时,就停下来(动图演示👇)
    在这里插入图片描述

    然后 tailB 再走,当 tailB 走到 尾节点 时,就停下来(动图演示👇)
    在这里插入图片描述

    注意:这里是走到 尾节点,也就是说当 尾节点next 指向 NULL 时,就停下来。

    然后再把 tailAtailB 进行比较,如果它们的 地址 相等,说明相交,就找交点;如果 地址 不相等,就返回 NULL

    既然 地址 相等,那我们就要找交点,但是得先求出 A链表B链表 的长度;

    定义两个整型 lenAlenB,分别用来表示长度,初始值设为 1

    计算 lenA 的过程👇
    在这里插入图片描述

    计算 lenB 的过程👇

    在这里插入图片描述
    注意:

    为什么把 lenAlenB初始值设为 1 呢?
     
    因为要求链表长度,也就是走到 尾节点 就结束了;
     
    也就说从第一个节点开始计算,当走到 尾节点 时,就结束,相当于 尾节点 没有计算,所以就少算了 1 个。

    然后就是求出 差距步,让 的链表先走 差距步,然后再一起走;

    此时 lenB 大于 lenA,求出 差距步1

    所以我们重新定义两个指针,longtList 指向 B 的头节点,shortList 指向 A 的头节点,然后让 longList 先走 差距步,也就是先走 1步(动图演示👇)
    在这里插入图片描述

    此时再让 longListshortList 一起走,走到相等的位置就停下来(动图演示👇)
    在这里插入图片描述
    注意:

    上面的图中给的链表是 B 长,A 短,但是实际情况有可能是 A 长,B 短;也有可能是 AB 一样长;
     
    所以我们要把长度进行判断,假设默认先设为 A 长,B 短;
     
    如果 lenA 大于 lenB,那么假设成立,就求 差距步
     
    如果 lenA 小于 lenB,那么说明假设不成立,重新定义即可。

    3. 代码实现

    接口代码

    struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
        struct ListNode* tailA, *tailB;
        tailA = headA;
        tailB = headB;
    
        int lenA = 1; // 存放A链表的长度
        int lenB = 1; // 存放B链表的长度
    
        // A链表找尾节点
        while (tailA->next) {
            tailA = tailA->next;
            ++lenA;
        }
    
        // B链表找尾节点
        while (tailB->next) {
            tailB = tailB->next;
            ++lenB;
        }
    
        // 如果不相等就返回NULL
        if (tailA != tailB) {
            return NULL;
        }
    
        // 相交,求交点,长的先走"差距步", 然后一起走
        struct ListNode* shortList = headA; // 假设A短
        struct ListNode* longList = headB; // 假设B长
        // 如果A的长度大于B
        if (lenA > lenB) {
            // 那么就交换一下
            longList = headA;
            shortList = headB;
        }
    
        // 求出差距步
        int gap = abs(lenA - lenB); // abs是求绝对值的函数
    
        // 长的先走差距步
        while (gap--) {
            longList = longList->next;
        }
    
        // 然后同时走
        while (shortList && longList) {
            if (shortList == longList) {
                return shortList;
            }
            shortList = shortList->next;
            longList = longList->next;
        }
    
        // 要加这个,不然会显示[编译出错]
        return NULL;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    提交结果
    在这里插入图片描述

  • 相关阅读:
    Java如何使用for each遍历LinkedList链表集合中的元素呢?
    如何面试网络安全NISP面试官通常会问什么(四)NISP管理中心
    python基础语法-文件操作及深浅拷贝(简单实用)
    redis(2)-hiredis-centos-ubuntu 下安装和使用
    NLP中的文本分类、实体识别、关系识别和三元组识别
    BufferParams in diplomacy-Parameter.scala
    二、企业快速开发平台Spring Cloud+Spring Boot+Mybatis+ElementUI之Lua 环境安装
    Selenium自动化脚本打包exe文件
    「学习笔记」KMP 算法
    【Vue 开发实战】基础篇 # 7:理解虚拟DOM及key属性的作用
  • 原文地址:https://blog.csdn.net/m0_63325890/article/details/126006653