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

2024-01-30 08:20

本文主要是介绍面试题 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;}
};

这篇关于面试题 02.07. 链表相交(力扣LeetCode)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/659638

相关文章

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

哈希leetcode-1

目录 1前言 2.例题  2.1两数之和 2.2判断是否互为字符重排 2.3存在重复元素1 2.4存在重复元素2 2.5字母异位词分组 1前言 哈希表主要是适合于快速查找某个元素(O(1)) 当我们要频繁的查找某个元素,第一哈希表O(1),第二,二分O(log n) 一般可以分为语言自带的容器哈希和用数组模拟的简易哈希。 最简单的比如数组模拟字符存储,只要开26个c

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后

深入手撕链表

链表 分类概念单链表增尾插头插插入 删尾删头删删除 查完整实现带头不带头 双向链表初始化增尾插头插插入 删查完整代码 数组 分类 #mermaid-svg-qKD178fTiiaYeKjl {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

leetcode-24Swap Nodes in Pairs

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode swapPairs(L

leetcode-23Merge k Sorted Lists

带头结点。 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(int x) { val = x; }* }*/public class Solution {public ListNode mergeKLists

建立升序链表

题目1181:遍历链表 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2744 解决:1186 题目描述: 建立一个升序链表并遍历输出。 输入: 输入的每个案例中第一行包括1个整数:n(1<=n<=1000),接下来的一行包括n个整数。 输出: 可能有多组测试数据,对于每组数据, 将n个整数建立升序链表,之后遍历链表并输出。 样例输