面试题 02.07. 链表相交(力扣LeetCode)

文章目录

  • 面试题 02.07. 链表相交
    • 题目描述
    • 解题思路
      • c++代码
      • 优化后c++代码

面试题 02.07. 链表相交

题目描述

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:
在这里插入图片描述
题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

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

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

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

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at ‘2’
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

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

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

提示:

  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 0 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listA 和 listB 没有交点,intersectVal 为 0
  • 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]

进阶:你能否设计一个时间复杂度 O(n) 、仅用 O(1) 内存的解决方案?

解题思路

简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等
为了方便举例,假设节点元素数值相等,则节点指针相等。
看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:
在这里插入图片描述
我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图:
在这里插入图片描述
此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

否则循环退出返回空指针。

c++代码

函数首先分别计算两个链表的长度,然后根据长度差将长链表的指针前移,使两个链表在剩余部分拥有相同的长度。接下来,同时遍历两个链表,直到找到相同的节点(即相交的节点),或者确定两个链表不相交并返回 nullptr。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        // 定义两个指针,分别指向两个链表的头节点
        ListNode* cura = headA;
        ListNode* curb = headB;

        // 定义两个变量,用于记录两个链表的长度
        int ansa = 0, ansb = 0;

        // 遍历链表A,计算其长度
        while(cura) {
            cura = cura->next;
            ansa++;
        }

        // 遍历链表B,计算其长度
        while(curb) {
            curb = curb->next;
            ansb++;
        }

        // 重置cura和curb指针,指向各自链表的头节点
        cura = headA;
        curb = headB;

        // 如果链表A比链表B长,将cura指针向前移动ansA - ansB个节点
        if(ansa > ansb) {
            int n = ansa - ansb;
            while(n--) cura = cura->next;

            // 从当前位置开始,逐个对比两个链表的节点是否相同
            while(cura != nullptr) {
                if(cura == curb)
                    return cura; // 如果找到相同的节点,说明这是相交的节点,返回该节点
                cura = cura->next; // 否则继续遍历链表
                curb = curb->next;
            }
        }
        // 如果链表B比链表A长,或者两链表等长(这时ansb - ansa为0,不会进入while循环),将curb指针向前移动ansB - ansA个节点
        else {
            int n = ansb - ansa;
            while(n--) curb = curb->next;

            // 从当前位置开始,逐个对比两个链表的节点是否相同
            while(curb != nullptr) {
                if(cura == curb)
                    return cura; // 如果找到相同的节点,说明这是相交的节点,返回该节点
                cura = cura->next; // 否则继续遍历链表
                curb = curb->next;
            }
        }

        // 如果两个链表不相交,返回nullptr
        return nullptr;
    }
};

优化后c++代码

首先,函数通过两个while循环分别计算链表A和B的长度。之后,再次初始化两个指针,指向两个链表的头节点。如果链表B比链表A长,则交换两者,确保cura始终指向较长的链表。之后将cura指针向前移动两个链表长度差值n的距离,以使得两个链表从尾部到当前位置的长度相等。最后,同步遍历两个链表,直到找到相交的节点。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        // 初始化两个指针从各自的链表头部开始
        ListNode* cura = headA;
        ListNode* curb = headB;

        // 初始化两个变量来记录两个链表的长度
        int ansa = 0, ansb = 0;

        // 遍历链表A,计算长度ansa
        while(cura) {
            cura = cura->next;
            ansa++;
        }

        // 遍历链表B,计算长度ansb
        while(curb) {
            curb = curb->next;
            ansb++;
        }

        // 重置cura和curb指向各自链表的头部
        cura = headA, curb = headB;

        // 如果链表B比链表A长,则交换两链表的头指针及长度,
        // 确保cura始终指向较长的链表
        if(ansb > ansa) {
            swap(ansa, ansb);
            swap(cura, curb);
        }

        // 计算两链表长度的差值
        int n = ansa - ansb;

        // 将指向较长链表的指针cura向前移动n个节点,达到与较短链表对齐
        while(n--) cura = cura->next;

        // 从对齐位置开始,同时遍历两个链表
        while(cura != nullptr) {
            // 如果两指针相遇,则返回相遇的节点,即为相交的起始节点
            if(cura == curb)
                return cura;

            // 否则继续向前遍历
            cura = cura->next;
            curb = curb->next;
        }

        // 如果没有交点,返回nullptr
        return nullptr;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【轮式平衡机器人】——TMS320F28069片内外设之ADC

一、ADC概述 这一部分不是我们的重点&#xff0c;原理分类啥的这里简要说明&#xff01; 步骤&#xff1a;采样、保持、量化、编码 将采样电平&#xff08;模拟值&#xff09;转换为数字值的方法&#xff1a;直接比较型&#xff08;并行ADC、逐次逼近型ADC&#xff09;&…

通俗易懂理解注意力机制(Attention Mechanism)

重要说明&#xff1a;本文从网上资料整理而来&#xff0c;仅记录博主学习相关知识点的过程&#xff0c;侵删。 一、参考资料 大话注意力机制&#xff08;Attention Mechanism&#xff09; 注意力机制(Attention Mechanism) 深度学习中的注意力机制 注意力机制 二、注意力…

关于最小系统板PCB设计后的一些反思

简介 趁着刚刚画完板子寄回来&#xff0c;在这里做一些记录。 板子状况 这里打烊了5块PCB&#xff0c;但是没有进行SMT贴片&#xff0c;后续如果有芯片可以焊接上去进行后续验证。 封装问题 这里可以看到&#xff0c;我这里两侧的排针都是焊盘&#xff0c;不是通孔&#…

【动态规划】【字符串】【前缀和】1639通过给定词典构造目标字符串的方案数

作者推荐 【动态规划】【字符串】【行程码】1531. 压缩字符串 本文涉及知识点 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 1639. 通过给定词典构造目标字符串的方案数 给你一个字符串列表 words 和一个目标字符串 tar…

编译Opencv3.3.1遇到的编译器无法识别的警告的问题解除:

问题描述&#xff1a; 本文&#xff0c;就是在一个硬件的SDK中用到了opencv3.3.1的版本&#xff0c;在笔者目前的VS2019,CUDA11版本下编译的问题和解决。在做Cmake的configure的时候&#xff0c;Cmake报了一个找不到编译器版本的错误, Selecting windows SDK version 10.0.1904…

TOP100 矩阵

1.73. 矩阵置零 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 提示&#xff1a; m matrix.lengthn matrix[0].length1 < m, n < 200-2^31 < matrix[i][j] < 2^31 - 1 思路&#xf…

EMQX 单机及集群搭建

目录 1. 通过 Yum 源安装&#xff08;CentOS7 单机安装&#xff09; 1.1. 通过以下命令配置 EMQX Yum 源&#xff1a; 1.2. 运行以下命令安装 EMQX&#xff1a; 1.3. 运行以下命令启动 EMQX&#xff1a; 1.4. 访问 http://192.168.88.130:18083&#xff0c;默认用户名: adm…

Java项目要不要部署在Docker里?

部署Java项目有很多种方式&#xff0c;传统的方式是直接在物理机或虚拟机上部署应用&#xff0c;但为什么现在容器化部署变得越来越流行&#xff0c; 个人觉得原因有以下几个&#xff1a; 1、 环境一致性&#xff1a;使用Docker可以确保开发、测试和生产环境的一致性&#xff…

如何使用保留可探测字段参数的方法解决视频监控管理平台EasyCVR无法启动的问题

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…

飞桨paddlespeech语音唤醒推理C INT8 定点实现

前面的文章&#xff08;飞桨paddlespeech语音唤醒推理C定点实现&#xff09;讲了INT16的定点实现。因为目前商用的语音唤醒方案推理几乎都是INT8的定点实现&#xff0c;于是我又做了INT8的定点实现。 实现前做了一番调研。量化主要包括权重值量化和激活值量化。权重值由于较小且…

Log4j2-24-log4j2 相同的日志打印 2 次

现象 相同的日志打印了两次&#xff0c;且因为日志的配置不同&#xff0c;导致脱敏的情况不一致。 代码与配置 代码 package com.ryo.log4j2.cfg.additivity;import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger;public class SimpleDemo…

JNPF低代码平台与其他低代码工具功能有什么不同?

JNPF低代码平台是一种新兴的技术解决方案&#xff0c;它可以帮助开发者快速构建应用程序而无需编写大量的代码。本文将深入了解JNPF低代码平台的常见类型与功能特点&#xff0c;帮助读者更好地理解和应用这项技术。 JNPF低代码平台的功能特点。首先&#xff0c;JNPF低代码平台具…

day28 回溯算法part4

93. 复原 IP 地址 中等 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 ‘.’ 分隔。 例如&#xff1a;“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址&#xff0c;但是 “0.011…

报错 Cannot read properties of undefined(reading‘addEventListener‘)如何解决

我在制作项目中遇到了一个问题&#xff0c;给大家分享一下&#xff0c;如下图&#xff1a; 问题&#xff1a;这是我给一个input输入框绑定的监听事件出现的报错 翻译&#xff1a;无法读取未定义的属性(读取 addEventListener ) 错误原因&#xff1a;js中操作的dom元素的函数方…

知识库是什么?为什么这么多企业都在用?

在信息化的时代&#xff0c;万物互联&#xff0c;企业获取、积累和应用知识的方式也因此发生了巨大的变化。有一项重要工具正是知识库&#xff0c;许多企业和组织都在广泛地使用它。那么&#xff0c;到底什么是知识库&#xff1f;为什么它能受到广泛的接纳和应用呢&#xff1f;…

MongoDB:从容器使用到 Mongosh、Python/Node.js 数据操作(结构清晰万字长文)

文章目录 1. 容器与应用之间的关系介绍2. 使用 Docker 容器安装 MongoDB3. Mongosh 操作3.1 Mongosh 连接到 MongoDB3.2 基础操作与 CRUD 4. Python 操作 MongoDB5. Nodejs 操作 MongoDB5.1 Mongodb 和 Mongoose5.2 推荐在项目中使用 Mongoose 参考文献 1. 容器与应用之间的关系…

数据质量和数据治理的关系 | 京东云技术团队

很多不太了解的人会认为&#xff1a;数据治理就是干数据清洗的。 近两年&#xff0c;在我们公司&#xff0c;数据治理团队在数据降本方面做的比较多&#xff0c;效果还不错&#xff0c;我们很多人可能以为&#xff1a;数据治理就是做数据清理的。 在京东科技集团数据治理工作…

如何使用Docker部署JSON Crack

文章目录 1. 在Linux上使用Docker安装JSONCrack2. 安装Cpolar内网穿透工具3. 配置JSON Crack界面公网地址4. 远程访问 JSONCrack 界面5. 固定 JSONCrack公网地址 JSON Crack 是一款免费的开源数据可视化应用程序&#xff0c;能够将 JSON、YAML、XML、CSV 等数据格式可视化为交互…

链接脚本常用命令(KEEP、MEMORY、PROVIDE、ENTRY、AT、ALIGN等)

1、命令介绍 命令作用KEEP保证该段一定在输出文件里&#xff0c;不会被丢弃MEMORY描述目标设备的内存情况&#xff0c;内存分几个区域&#xff0c;每个内存区域的属性PROVIDE从链接脚本导出符号给C语言或者汇编语言使用ENTRY程序入口AT指定段的加载地址ALIGN指定地址的对齐LOA…

入门产品经理详细教程!PM常用工具|岗位职责|学习书单|能力模型|与项目经理的区别

移动互联网和AI时代&#xff0c;产品经理无疑是备受瞩目的工作&#xff0c;产品经理负责提出各种创意&#xff0c;同时协调各种资源&#xff0c;推动创意落地实现产品从0到1&#xff0c;而且互联网上对产品经理这个职业也有诸多赞誉—— 产品经理是最接近CEO的岗位产品经理是站…