力扣 - 剑指 Offer 52. 两个链表的第一个公共节点
题目
思路1(栈)
- 若两个链表相遇,则从它开始相遇的地方到链表末尾应该都是相同的,那么我们可以将两个链表分别放入两个栈中,然后依次循环比较两个栈顶的节点,同时用
pre记录上一个节点,直到当前两个栈顶节点不相等,那么pre节点就是他们开始相遇的地方
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
LinkedList<ListNode> stack1 = new LinkedList<>();
LinkedList<ListNode> stack2 = new LinkedList<>();
// 使用两个栈分别存储两个链表的元素
while (headA != null) {
stack1.push(headA);
headA = headA.next;
}
while (headB != null) {
stack2.push(headB);
headB = headB.next;
}
// 若两个链表存在相同的节点,则两个栈pop出来的节点应该是一样的
// 如果pop出来的不一样,说明上一个pop出来相同节点才是相遇开始的节点
// 因此我们需要pre来记录上一个相同的节点,初始值要为null,如果没有相遇,那么会直接返回null
ListNode pre = null;
while (!stack1.isEmpty() && !stack2.isEmpty()) {
ListNode p1 = stack1.pop();
ListNode p2 = stack2.pop();
if (p1 != p2) {
break;
}
// 如果没有相遇,就不会执行这条语句,因此此时pre为 null,返回的值也是 null
pre = p1;
}
// 返回结果
return pre;
}
}
复杂度分析
- 时间复杂度:\(O(N+M)\)
- 空间复杂度:\(O(N+M)\)
思路2(差值法)
- 先分别计算两个链表的长度记为
lengthA和lengthB,得到他们的差值n,让长的那个链表先走n步,然后两个链表再一起走,第一个相等的地方,则是链表开始相遇的地方
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int lengthA = 0;
int lengthB = 0;
ListNode pA = headA;
ListNode pB = headB;
// 先获取两个链表的长度
while (pA != null) {
pA = pA.next;
lengthA++;
}
while (pB != null) {
pB = pB.next;
lengthB++;
}
// 计算链表长度差n,将长的链表先走n步
int n = lengthA > lengthB ? lengthA - lengthB : lengthB - lengthA;
while (lengthA > lengthB && n > 0) {
headA = headA.next;
n--;
}
while (lengthB > lengthA && n > 0) {
headB = headB.next;
n--;
}
// 然后两个链表才开始同时一起走
// 知道两个节点相等 或者 都为null的时候结束循环
while (headA != headB) {
headA = headA.next;
headB = headB.next;
}
return headA;
}
}
复杂度分析
- 时间复杂度:\(O(N+M)\)
- 空间复杂度:\(O(1)\)
思路3(双指针)
- 使用两个指针
pA和pB分别指向两个链表,然后同时前进,如果到了链表末尾,就跳到另一条链表的头节点(要保证不会再跳回来,否则导致死循环) - 在这过程中,要判断节点是否相等,第一次相等的地方就是相交的地方,如果没有那就返回
null - 在
while中的判断条件要为当前两个节点是否相等,因为不这样的话,如果不存在相交的节点,那么循环就会一直重复下去;如果判断条件为当前两个节点是否相等的话,如果没有相交节点也不会一直循环下去,因为两个指针遍历的长度都为两个链表长度之和,所以最后都会指向null,此时都为null相等,跳出循环
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode pA = headA;
ListNode pB = headB;
// 判断是否相等,遇到相同节点,结束循环;如果链表中没有相同节点,那么跳出循环的条件是他们都为 null 的时候
while (pA != pB) {
// 判断的要为当前节点
// 如果判断的是next节点,那么到时候就会导致pA、pB永远不会是null
if (pA == null) {
pA = headB;
} else {
pA = pA.next;
}
if (pB == null) {
pB = headA;
} else {
pB = pB.next;
}
}
return pA;
}
}
复杂度分析
- 时间复杂度:\(O(N)\)
- 空间复杂度:\(O(1)\)
思路4(哈希表)
- 先选择其中一个链表,将其节点全部加入到哈希表中,然后再开始遍历另一个链表,同时也加入到哈希表中
- 如果加入的节点和哈希表冲突了,那么这个节点就是交点
代码
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
HashSet<ListNode> set = new HashSet<>();
// 遍历一次,将链表A里的所有节点添加到set中
while (headA != null) {
set.add(headA);
headA = headA.next;
}
// 再遍历一次链表B,同时将链表的节点添加到set中,如果添加失败返回false,那么说明找到相同的那个节点了,直接返回该节点
while (headB != null) {
if (!set.add(headB)) {
return headB;
}
headB = headB.next;
}
// 如果遍历链表B的时候都没有找到,说明不存在相同的节点,就返回 null
return null;
}
}
复杂度分析
- 时间复杂度:\(O(N+M)\)
- 空间复杂度:\(O(N)\),哈希表所占空间大小
力扣 - 剑指 Offer 52. 两个链表的第一个公共节点的更多相关文章
- 剑指 Offer 52. 两个链表的第一个公共节点 + 链表 + 第一个公共结点 + 双指针
剑指 Offer 52. 两个链表的第一个公共节点 Offer_52 题目详情 题解分析 可以使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结 ...
- 每日一题 - 剑指 Offer 52. 两个链表的第一个公共节点
题目信息 时间: 2019-07-03 题目链接:Leetcode tag: 单链表 难易程度:简单 题目描述: 输入两个链表,找出它们的第一个公共节点. 示例: A: a1 -> a2 \ - ...
- 剑指 Offer 52. 两个链表的第一个公共节点
题目链接 题目描述: 我的题解: 方法一:双指针法 思路分析: 声明两个指针p1,p2 分别指向链表A.链表B. 然后分别同时逐结点遍历 当 p1 到达链表 headA 的末尾时,重新定位到链表 he ...
- [LeetCode]剑指 Offer 52. 两个链表的第一个公共节点
题解 nodeA走一个链表A(A独有+公共),再走B独有的长度, nodeB走一个链表B(B独有+公共),再走A独有的长度. 结果:两者相遇点即为交点:若没有交点,两者都走到null,会返回null. ...
- 【Java】 剑指offer(52) 两个链表的第一个公共结点
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 输入两个链表,找出它们的第一个公共结点. 思路 蛮力法:遍历第一个 ...
- 剑指offer——55两个链表的第一个公共节点
题目描述 输入两个链表,找出它们的第一个公共结点. 题解: 分别遍历两个链表到链尾,并计算其长度,若最后一个节点相同,则存在公共节点 然后让长链表指针从头先移动长度差个节点,然后两个链表指针一起移动, ...
- 【剑指offer】两个链表的第一个公共结点,C++实现
原创文章,转载请注明出处! 博客文章索引地址 # 题目 #举例 如果两个单向链表有公共的节点,那么这两个链表从第一个公共结点开始,之后所有结点都是重合的,不可能再出现分叉.拓扑结构如下图所示: # 思 ...
- Go语言实现:【剑指offer】两个链表的第一个公共结点
该题目来源于牛客网<剑指offer>专题. 输入两个链表,找出它们的第一个公共结点. Go语言实现: //长度长的先走个长度差,然后ab一起比较后面结点 //长度一样,公共结点可能在首结点 ...
- 【剑指offer】两个链表的第一个公共结点
一.题目: 输入两个链表,找出它们的第一个公共结点. 二.思路: 思路一:模拟数组,进行两次遍历,时间复杂度O(n2) 思路二:假定 List1长度: a+n List2 长度:b+n, 且 a&l ...
随机推荐
- Java编程思想 第九章 接口
第九章 接口 抽象类和抽象方法 抽象:从具体事物抽出.概括出它们共同的方面.本质属性与关系等,而将个别的.非本质的方面.属性与关系舍弃,这种思维过程,称为抽象. 这句话概括了抽象的概念,而在Java中 ...
- vue 快速入门 系列 —— vue-router
其他章节请看: vue 快速入门 系列 Vue Router Vue Router 是 Vue.js 官方的路由管理器.它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌. 什么是路由 ...
- PHP审计之PHP反序列化漏洞
PHP审计之PHP反序列化漏洞 前言 一直不懂,PHP反序列化感觉上比Java的反序列化难上不少.但归根结底还是serialize和unserialize中的一些问题. 在此不做多的介绍. 魔术方法 ...
- RabbitMQ的消息可靠性(五)
一.可靠性问题分析 消息的可靠性投递是使用消息中间件不可避免的问题,不管是使用哪种MQ都存在这种问题,接下来要说的就是在RabbitMQ中如何解决可靠性问题:在前面 在前面说过消息的传递过程中有三个对 ...
- uoj167 元旦老人与汉诺塔(记忆化搜索)
QwQ太懒了,题目直接复制uoj的了 QwQ这个题可以说是十分玄学的一道题了 首先可以暴搜,就是\(dfs\)然后模拟每个过程是哪个柱子向哪个柱子移动 不多解释了,不过实现起来还是有一点点难度的 直接 ...
- 初学Python-day1 运算符和数据类型
- 【数据结构与算法Python版学习笔记】图——强连通分支
互联网 我们关注一下互联网相关的非常巨大图: 由主机通过网线(或无线)连接而形成的图: 以及由网页通过超链接连接而形成的图. 网页形成的图 以网页(URI作为id)为顶点,网页内包含的超链接作为边,可 ...
- 让全链路压测变得更简单!Takin2.0重磅来袭!
自Takin社区版1.0发布两个多月以来,有很多测试同学陆续在各自的工作中运用了起来,其中包括金融.电商.物流.出行服务等行业.这个过程中我们收到了很多同学的反馈建议,同时也了解到很多同学在落地全链路 ...
- the Agiles Scrum Meeting 2
会议时间:2020.4.10 21:00 1.每个人的工作 今天已完成的工作 yjy:debug:班级创建了个人项目不能访问班级:教师窗口的前端bug. issues:Bug:教师创建博客时显示项目为 ...
- 大闸蟹的 O O 战记
一. 第四单元架构设计分析 第一次作业,UML类图 第一次作业的主要任务是完成对UML类图的解析并实现查询等操作,需要在课程组给定的框架中添加函数.对于UML类图,其存储是按照元素来存储的,其将所有的 ...