面试题 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;}}// 如果两个链表不相交,返回nullptrreturn 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,计算长度ansawhile(cura) {cura = cura->next;ansa++;}// 遍历链表B,计算长度ansbwhile(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;}// 如果没有交点,返回nullptrreturn nullptr;}
};

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell

目录 一.运行方式 二.编程习惯 三.变量 3.1变量的命名 3.3普通变量(局部变量) 3.4特殊变量 3.5变量子串 3.6变量赋值 四.运算方式 4.1$(( )) 4.2let 4.3expr 4.4bc(小数运算) 4.5$[ ] 4.6awk 4.7总结运算方式 五.条件测试语句 5.1文件 5.2条件测试表达式…

IDEA:git 回滚本地提交-git 选择 Reset Current Branch to

前言 回滚提交到本地但是还没有 Push 上去的提交 选择我们要回滚的节点&#xff0c;然后点击 git 选择 Reset Current Branch to… 再选择 Hard 。当我们点击 Reset 的时候&#xff0c;代码就会回滚到单前选中的这个版本

数字时代的工作利器

当谈到使用工作软件的多样选择时&#xff0c;就像是探索灯塔下的海洋般令人兴奋。无论是新进入办公领域的小白&#xff0c;还是经验丰富的职场老将&#xff0c;我们都渴望找到那些能在工作中为我们点燃生产力和创造力的魔法工具。下面是五款备受欢迎且富有创造力的工作软件推荐…

专业120+总分400+宁波大学912信号与系统考研经验电子信息通信集成电路光电

今年考研顺利上岸&#xff0c;专业课912信号与系统120&#xff0c;总分400&#xff0c;被宁波大学录取&#xff0c;回望这一年的复习有过迷茫和犹豫&#xff0c;也有过坚持和坚强&#xff0c;总结一下自己的复习得失&#xff0c;希望对大家复习有所帮助。专业课&#xff1a; 前…

【重磅发布】已开放!模型师入驻、转格式再升级、3D展示框架全新玩法…

1月23日&#xff0c;老子云正式发布全新版本。此次新版本包含多板块功能上线和升级&#xff0c;为用户带来了含模型师入驻、三维格式在线转换升级、模型免费增值权益开放、全新3D展示框架等一系列精彩内容&#xff01; 1月23日&#xff0c;老子云正式发布全新版本。此次新版本…

【vue】图片加载骨架

一、前言 在网速较低或者网站的服务器宽带只有几MB的情况下&#xff0c;网页中的图片加载时&#xff0c;要么空白&#xff0c;要么像打印机一样一行一行地“扫描”出来&#xff0c;为了提升用户体验&#xff0c;可以给图片标签外加一层骨架。 无骨架 有骨架 二、详细设计 每张…

现在我有三个代码块,分别都调用了同一个接口使用相同的数据,请问怎么精简代码,让他只调用一次接口,将数据存储起来让其他函数共同使用.

问题描述: 现在我有三个代码块: 一: const getData async () > {console.log(触发了getData接口)let resultData await getActivityInfo(activityId);console.log(resultData,resultData)let id resultData.id;let shareImg resultData.shareImglet shareSubtitle res…

JWT(JSON Web Token)详解以及在go-zero中配置的方法

目的 对用户进行身份认证和信息交换 RFC 7519 传统方式 通过session保存对话信息&#xff0c;服务端返回一个session id&#xff0c;用户保存这个id在cookie内&#xff0c;然后每次请求都传给服务端 局限性 对于服务器集群难以向每个服务器共享同一session jwt的方式是…

备战蓝桥杯---数据结构与STL应用(基础实战篇1)

话不多说&#xff0c;直接上题&#xff1a; 当然我们可以用队列&#xff0c;但是其插入复杂度为N,总的复杂度为n^2,肯定会超时&#xff0c;于是我们可以用链表来写&#xff0c;同时把其存在数组中&#xff0c;这样节点的访问复杂度也为o(1).下面是AC代码&#xff1a; 下面我们来…

学习MySQL仅此一篇就够了(视图)

视图 介绍及基本语法 视图&#xff08;View&#xff09;是一种虚拟存在的表。视图中的数据并不在数据库中实际存在&#xff0c;行和列数据来自定义视 图的查询中使用的表&#xff0c;并且是在使用视图时动态生成的。 通俗的讲&#xff0c;视图只保存了查询的SQL逻辑&#xf…

我在代码随想录|写代码Day20之二叉树-700. 二叉搜索树中的搜索,98. 验证二叉搜索树,530.二叉搜索树的最小绝对差

学习目标&#xff1a; 博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门 &#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d; ☆*: .&#xff61;. o(≧▽≦)…

TypeScript(八) number和string

1. TypeScript number 1.1. 描述 Number对象是原始数值的包装对象。 1.2.语法 var num new Number(value);;注意&#xff1a;如果一个参数值不能转换为一个数字&#xff0c;将返回NaN&#xff08;非数字值&#xff09;。 1.3. 对象属性 属性描述MAX_VALUE可表示的最大的数…