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

前言

Wassup guys!我是Edison

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

Let’s get it!

在这里插入图片描述


文章目录

  • 1. 题目分析
  • 2. 思路分析
    • 判断相交
    • 求出交点
    • 实现步骤
  • 3. 代码实现


1. 题目分析

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
 
图示两个链表在节点 c1 开始相交:
LeetCode每日一练 —— 160. 相交链表_第1张图片
题目数据 保证 整个链式结构中不存在环。
 
注意,函数返回结果后,链表必须 保持其原始结构

示例 1:
LeetCode每日一练 —— 160. 相交链表_第2张图片

示例 2:
LeetCode每日一练 —— 160. 相交链表_第3张图片

示例 3:
LeetCode每日一练 —— 160. 相交链表_第4张图片

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 走到 尾节点 时,就停下来(动图演示)
LeetCode每日一练 —— 160. 相交链表_第5张图片

然后 tailB 再走,当 tailB 走到 尾节点 时,就停下来(动图演示)
LeetCode每日一练 —— 160. 相交链表_第6张图片

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

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

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

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

计算 lenA 的过程
LeetCode每日一练 —— 160. 相交链表_第7张图片

计算 lenB 的过程

LeetCode每日一练 —— 160. 相交链表_第8张图片
注意:

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

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

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

所以我们重新定义两个指针,longtList 指向 B 的头节点,shortList 指向 A 的头节点,然后让 longList 先走 差距步,也就是先走 1步(动图演示)
LeetCode每日一练 —— 160. 相交链表_第9张图片

此时再让 longListshortList 一起走,走到相等的位置就停下来(动图演示)
LeetCode每日一练 —— 160. 相交链表_第10张图片
注意:

上面的图中给的链表是 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;
}

提交结果
LeetCode每日一练 —— 160. 相交链表_第11张图片

你可能感兴趣的:(算法刷题宝典,链表,leetcode,算法,数据结构,相交链表)