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;
}

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

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Albert Edison

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值