相遇于此,“相交链表”问题的两种思路

news2024/12/29 8:59:18

在这里插入图片描述

本篇博客会讲解力扣“160. 相交链表”的解题思路,这是题目链接。

老规矩,先来审题。这道题的题干有点长,简而言之,就是判断2个链表是否相交,如果相交就返回第一个相交结点,不相交就返回NULL。看看题目原文:
在这里插入图片描述
在这里插入图片描述
以下是几个示例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
以下是提示和进阶要求:
在这里插入图片描述
接下来讲解我想到的解题思路,如果有更好的思路,可以在评论区提出。

思路1

这道题本质上是2小问:

  1. 链表是否相交?
  2. 如果相交,请找出第一个相交结点。

对于第一个问题,判断方法其实很简单,如果尾结点相同,那么2个链表相交。

如果相交的话,如何找出第一个相交结点呢?我们可以在第一步找出尾结点的时候顺便统计2个链表的长度,并求出长度的差。接着让长链表先走差距步,2个链表再同时走,第一个相遇的结点就是我们要找的结点。

开始写代码:首先先找尾结点。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *tailA = headA, *tailB = headB;
    // 找尾结点
    while (tailA->next)
    {
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        tailB = tailB->next;
    }
}

如果尾结点不相同,则链表一定不相交。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *tailA = headA, *tailB = headB;
    // 找尾结点
    while (tailA->next)
    {
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        tailB = tailB->next;
    }

    // 尾结点不同,链表不相交
    if (tailA != tailB)
    {
        return NULL;
    }
}

如果相交,就应该求出链表的第一个相交结点。我们得让长的链表先走差距步,所以应该先求出2个链表的长度,在前面找尾结点的同时就可以顺便求一下。注意为了严谨起见,lenA和lenB都被初始化成1,不然会少算一个结点。计算差距可以调用abs函数求绝对值。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *tailA = headA, *tailB = headB;
    int lenA = 1, lenB = 1;
    // 找尾结点,顺便求长度
    while (tailA->next)
    {
        ++lenA;
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        ++lenB;
        tailB = tailB->next;
    }

    // 尾结点不同,链表不相交
    if (tailA != tailB)
    {
        return NULL;
    }

    // 长度差距,取差的绝对值
    int gap = abs(lenA - lenB);
}

接下来我们得知道这2个链表谁长谁短。方法很简单,先假设A长B短,如果不是这样,就修正一下。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *tailA = headA, *tailB = headB;
    int lenA = 1, lenB = 1;
    // 找尾结点,顺便求长度
    while (tailA->next)
    {
        ++lenA;
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        ++lenB;
        tailB = tailB->next;
    }

    // 尾结点不同,链表不相交
    if (tailA != tailB)
    {
        return NULL;
    }

    // 长度差距,取差的绝对值
    int gap = abs(lenA - lenB);

    // 判断链表谁长谁短
    // 假设A长B短
    struct ListNode *longList = headA, *shortList = headB;
    // 不满足就修正
    if (lenA < lenB)
    {
        longList = headB;
        shortList = headA;
    }
}

接下来让长链表先走差距步:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *tailA = headA, *tailB = headB;
    int lenA = 1, lenB = 1;
    // 找尾结点,顺便求长度
    while (tailA->next)
    {
        ++lenA;
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        ++lenB;
        tailB = tailB->next;
    }

    // 尾结点不同,链表不相交
    if (tailA != tailB)
    {
        return NULL;
    }

    // 长度差距,取差的绝对值
    int gap = abs(lenA - lenB);

    // 判断链表谁长谁短
    // 假设A长B短
    struct ListNode *longList = headA, *shortList = headB;
    // 不满足就修正
    if (lenA < lenB)
    {
        longList = headB;
        shortList = headA;
    }

    // 长链表先走差距步
    while (gap--)
    {
        longList = longList->next;
    }
}

2个链表同时走,直到相遇。相遇的结点就是第一个相交结点。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *tailA = headA, *tailB = headB;
    int lenA = 1, lenB = 1;
    // 找尾结点,顺便求长度
    while (tailA->next)
    {
        ++lenA;
        tailA = tailA->next;
    }
    while (tailB->next)
    {
        ++lenB;
        tailB = tailB->next;
    }

    // 尾结点不同,链表不相交
    if (tailA != tailB)
    {
        return NULL;
    }

    // 长度差距,取差的绝对值
    int gap = abs(lenA - lenB);

    // 判断链表谁长谁短
    // 假设A长B短
    struct ListNode *longList = headA, *shortList = headB;
    // 不满足就修正
    if (lenA < lenB)
    {
        longList = headB;
        shortList = headA;
    }

    // 长链表先走差距步
    while (gap--)
    {
        longList = longList->next;
    }

    // 同时走,直到相遇
    while (longList != shortList)
    {
        longList = longList->next;
        shortList = shortList->next;
    }

    // 相遇点即为第一个交点
    return longList;
}

在这里插入图片描述
这样就通过了。

思路2

不过本题还有一个更简单的解法:2个链表同时向后走,如果走到NULL,就转移到另一个链表的头,直到相遇为止。若相遇点为NULL,则不相交,否则相遇点为第一个交点。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *curA = headA, *curB = headB;
    while (curA != curB)
    {
        // 如果没走到空,就向后走
        // 如果走到空,就转移到另一个链表的头
        if (curA)
            curA = curA->next;
        else
            curA = headB;

        if (curB)
            curB = curB->next;
        else
            curB = headA;
    }

    // 相遇点为NULL,则不相交
    // 若相交,则相遇点为第一个交点
    return curA;
}

在这里插入图片描述
这种解法是不是很巧妙?但是你大概率是想不到的,所以还是老老实实的用第一种解法吧。

本解法的原理是:设前缀为a和b,后缀为m(若不相交则m==0),若前缀相等,则走a(b)步相遇;若前缀不等,则走a+b+m步后相遇。

总结

相交链表问题的解题思路如下:

  1. 先找出尾结点,如果尾结点相同则相交,否则不相交。
  2. 找尾结点时顺便求出链表长度,计算出长度差距。
  3. 判断哪个链表长,哪个链表短的方法:先假设,如果不满足假设就修正。
  4. 让长链表先走差距步,再同时走,直到相遇,相遇点就是第一个交点。
  5. 巧妙的解法:大家同时向前走,如果没碰着,就换条道。

感谢大家的阅读!

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

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

相关文章

轻松打造完美客户服务系统,这4个关键点不容错过

客户服务对于一个企业来说非常重要&#xff0c;有以下几个原因&#xff1a; 1、建立客户忠诚度&#xff1a;通过提供高质量的客户服务&#xff0c;可以增加客户满意度和忠诚度。这将有助于企业保持竞争优势并吸引新客户。 2、提高客户满意度&#xff1a;客户对企业的服务感到…

MySQL 升级到 8.0 变慢问题分析

1. 背景介绍 前段时间&#xff0c;客户线上 MySQL 版本从 5.7.29 升级到 8.0.25。 升级完成之后&#xff0c;放业务请求进来&#xff0c;没到一分钟就开始出现慢查询&#xff0c;然后&#xff0c;慢查询越来越多&#xff0c;业务 SQL 出现堆积。 整个过程持续了大概一个小时&…

Java学习笔记 --- Stream流

一、体验Stream流【理解】 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素 把集合中所有以"张"开头的元素存储到一个新的集合 把"张"开头的集合中的长度为3的元素存储到一个新的集合 遍历上一步得到的集合 …

使用群晖NAS Mail Server搭建个性化邮件系统

准备工作 一个顶级域名可以获取公网IP的宽带路由使用DDNS功能&#xff0c;或使用群晖自带DDNS&#xff0c;解析顶级域名可以做“端口映射”的路由器 搭建开始 step1&#xff1a;安装套件 登录群晖NAS&#xff0c;打开[套件中心]&#xff0c;搜索“mail”&#xff0c;安装如…

idea-easyYapi的使用

链接: EasyYapi官方文档. 网上搜到的easyYapi基本上都是千篇一律&#xff0c;比较浅&#xff0c;稍微有点定制的东西都搜不到&#xff0c;帮此把自己的一些心得写出来&#xff0c;后续有新发现也会继续更新 第一步&#xff1a;安装插件 第二步&#xff1a;配置数据 yapi的t…

运营商大数据助力贷款行业快速精准获取意向客户

流量&#xff0c;是企业发展的一大痛点。随着市场格局不断变化&#xff0c;获取流量越来越成为企业摆脱发展困局的一种重要途径&#xff0c;如何在庞大的市场竞争中&#xff0c;实现自身的流量突破&#xff0c;也成为企业所要解决的首要问题。 贷款行业的竞争也很强烈&#xf…

一文总结MySQL面试知识点

文章目录 知识点1 定位慢查询2 存储引擎3 索引4 SQL优化5 事务6 主从同步7 分库分表 问答题1 如何定位慢查询2 那这个SQL语句执行很慢, 如何分析呢&#xff1f;3 MYSQL支持的存储引擎有哪些, 有什么区别 ?4 了解过索引吗&#xff1f;&#xff08;什么是索引&#xff09;5 索引…

录取分数爆降102分,只招一个人也敢报考的狠人!

本期为大家整理热门院校-“华南理工大学”的择校分析&#xff0c;这个择校分析专题会为大家结合&#xff1a;初试复试占比、复试录取规则&#xff08;是否公平&#xff09;、往年录取录取名单、招生人数、分数线、专业课难度等进行分析。希望能够帮到大家! –所有数据来源于研…

排班工具小程序开源版开发

排班工具小程序开源版开发 以下是排班工具小程序可能包含的功能列表&#xff1a; 用户注册和登录功能&#xff0c;支持微信登录和手机号登录。排班管理功能&#xff0c;包括创建、编辑、删除和查询排班表。排班表展示功能&#xff0c;支持按天、周、月等不同时间维度展示排班…

Apache DolphinScheduler 开源之夏学生项目申请开启,6 大课题等你来拿万元奖金!

开源之夏 2023 学生报名已经正式开启&#xff01;Apache DolphinScheduler 今年继续参与开源之夏的活动&#xff0c;2023 年 4 月 29 日-6 月 3 日 15:00 UTC8&#xff0c;同学们可以在开源之夏官网 https://summer-ospp.ac.cn/ 找到 Apache DolphinScheduler 下的项目&#xf…

i春秋 Misc Web 爆破-2

审计一下代码&#xff0c;和爆破-1的区别是&#xff0c;没有了正则匹配&#xff0c;且可变变量$$a变成了普通变量$a&#xff1b; 尝试像爆破-1那样传入超全局变量$GLOBALS 根据回显&#xff0c;我们发现flag不在变量中&#xff08;它还嘲笑我们“too young too simple”太年轻…

后端注册表单验证器实现

视图函数在去注册用户之前需要进行验证&#xff0c;表单验证需要先下载 flask-wtf 在终端执行&#xff1a; pip install flask-wtf新建forms.py import wtforms from wtforms.validators import Email,Length,EqualTo from models import UserModel,EmailCaptchaModel# Form…

详细的步骤在VirtualBox 上安装 CentOS 7

下面是详细的步骤来安装 CentOS 7 在 VirtualBox 上&#xff1a; 下载 CentOS 7 ISO 镜像文件&#xff1a; 前往 CentOS 官方网站的镜像下载页面&#xff1a;Download在页面上找到适合你系统架构的 CentOS 7 ISO 镜像文件&#xff0c;并下载到本地。 安装 VirtualBox&#x…

为什么大部分企业都选择加密软件来防止数据泄露?

加密软件是使用加密算法对数据或信息进行编码转换的软件&#xff0c;目的是防止未授权访问与保护敏感内容。它是实现加密技术的重要手段&#xff0c;为用户提供了简单易用的加解密功能&#xff0c;无需深入了解复杂的数学原理。 加密软件使用的加密算法通常采用对称与非对称算法…

16 KVM虚拟机配置-其他常见配置项

文章目录 16 KVM虚拟机配置-其他常见配置项16.1 概述16.2 元素介绍16.3 配置示例 16 KVM虚拟机配置-其他常见配置项 16.1 概述 除系统资源和虚拟设备外&#xff0c;XML配置文件还需要配置一些其他元素&#xff0c;本节介绍这些元素的配置方法。 16.2 元素介绍 iothreads&…

干货丨手把手教会群晖Mailplus设置及邮件免拒收(SPF、DMARC、DKIM)

开篇之前&#xff0c;我想说通过群晖 Mailplus Server 自建一个邮件服务器绝对是一个非常有成就感的事情&#xff0c;搭建 过程中我们可以学习到邮件服务使用的协议&#xff0c;端口号&#xff0c;MX解析等很多知识。如果你已经准备好&#xff0c;那就让 我们开始吧。 前期准备…

前端013_标签模块_新增功能

标签模块_新增功能 1、需求分析2、新增窗口实现3、列表引用新增组件4、关闭弹出窗口5、校验表单数据6、提交表单数据6.1 EasyMock 添加新增模拟接口6.2、Api 调用接口1、需求分析 点击 新增 按钮后,对话框形式弹出新增窗口输入类别信息后,点击 确定 提交表单数据; 2、新增窗…

DARWIN Survival of the Fittest Fuzzing Mutators读论文笔记

DARWIN: Survival of the Fittest Fuzzing Mutators 作者背景 达姆施塔特工业大学&#xff1a;成立于1877年&#xff0c;是德国著名理工科大学 ‡萨格勒布大学: 是克罗地亚最大的大学&#xff0c;也是该地区历史最悠久的大学 拉德堡德大学:位于荷兰奈梅亨市&#xff0c;又称奈梅…

Redis与SpringBoot的集成:自定义RedisTemplate类,创建一个工具类:可以帮助我们更好的使用redis中的API

这里使用的环境是在windows环境下&#xff0c;也可以放在服务器中&#xff0c;只要知道端口号和ip即可&#xff0c;如果有不知道怎么部署环境的可以看这篇文章去在Windows环境下去部署redis环境redis之jedis&#xff1a;通过redis的API与Java的集成_不想睡醒的梦的博客-CSDN博客…

css的clip-path学习

文章目录 clip-path的几个值polygon多边形circle圆形ellipse椭圆形inset 矩形round后面是四个角的度数 一个简单的应用&#xff0c;比如画一段曲线 参考博文 clip-path的几个值 自己学习后&#xff0c;先把clip-path理解为在原图上绘制轮廓&#xff0c;显示的内容是轮廓内的内…