题目

剑指 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(差值法)

  • 先分别计算两个链表的长度记为lengthAlengthB,得到他们的差值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(双指针)

  • 使用两个指针pApB分别指向两个链表,然后同时前进,如果到了链表末尾,就跳到另一条链表的头节点(要保证不会再跳回来,否则导致死循环)
  • 在这过程中,要判断节点是否相等,第一次相等的地方就是相交的地方,如果没有那就返回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. 两个链表的第一个公共节点的更多相关文章

  1. 剑指 Offer 52. 两个链表的第一个公共节点 + 链表 + 第一个公共结点 + 双指针

    剑指 Offer 52. 两个链表的第一个公共节点 Offer_52 题目详情 题解分析 可以使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结 ...

  2. 每日一题 - 剑指 Offer 52. 两个链表的第一个公共节点

    题目信息 时间: 2019-07-03 题目链接:Leetcode tag: 单链表 难易程度:简单 题目描述: 输入两个链表,找出它们的第一个公共节点. 示例: A: a1 -> a2 \ - ...

  3. 剑指 Offer 52. 两个链表的第一个公共节点

    题目链接 题目描述: 我的题解: 方法一:双指针法 思路分析: 声明两个指针p1,p2 分别指向链表A.链表B. 然后分别同时逐结点遍历 当 p1 到达链表 headA 的末尾时,重新定位到链表 he ...

  4. [LeetCode]剑指 Offer 52. 两个链表的第一个公共节点

    题解 nodeA走一个链表A(A独有+公共),再走B独有的长度, nodeB走一个链表B(B独有+公共),再走A独有的长度. 结果:两者相遇点即为交点:若没有交点,两者都走到null,会返回null. ...

  5. 【Java】 剑指offer(52) 两个链表的第一个公共结点

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 输入两个链表,找出它们的第一个公共结点. 思路 蛮力法:遍历第一个 ...

  6. 剑指offer——55两个链表的第一个公共节点

    题目描述 输入两个链表,找出它们的第一个公共结点. 题解: 分别遍历两个链表到链尾,并计算其长度,若最后一个节点相同,则存在公共节点 然后让长链表指针从头先移动长度差个节点,然后两个链表指针一起移动, ...

  7. 【剑指offer】两个链表的第一个公共结点,C++实现

    原创文章,转载请注明出处! 博客文章索引地址 # 题目 #举例 如果两个单向链表有公共的节点,那么这两个链表从第一个公共结点开始,之后所有结点都是重合的,不可能再出现分叉.拓扑结构如下图所示: # 思 ...

  8. Go语言实现:【剑指offer】两个链表的第一个公共结点

    该题目来源于牛客网<剑指offer>专题. 输入两个链表,找出它们的第一个公共结点. Go语言实现: //长度长的先走个长度差,然后ab一起比较后面结点 //长度一样,公共结点可能在首结点 ...

  9. 【剑指offer】两个链表的第一个公共结点

    一.题目: 输入两个链表,找出它们的第一个公共结点. 二.思路: 思路一:模拟数组,进行两次遍历,时间复杂度O(n2) 思路二:假定 List1长度: a+n  List2 长度:b+n, 且 a&l ...

随机推荐

  1. 🚴‍♂️全套MySQL数据库教程_Mysql基础入门教程,零基础小白自学MySQL数据库必备教程☔ #002 # 第二单元 MySQL数据类型、操作表#

    二.本单元知识点概述 (Ⅰ)知识点概述 二.本单元教学目标 (Ⅰ)重点知识目标 1.Mysql的数据类型2.如何选择数据类型3.创建表4.修改表5.删除表 (Ⅱ)能力目标 1.熟练创建数据库及删除数据 ...

  2. 高德最佳实践:Serverless 规模化落地有哪些价值?

    作者 | 何以然(以燃) 导读:曾经看上去很美.一直被观望的 Serverless,现已逐渐进入落地的阶段.今年的"十一出行节",高德在核心业务规模化落地 Serverless,由 ...

  3. web_security学习路线

    一.了解黑客是如何工作的 1.在虚拟机配置Linux系统 2.漏洞测试工具 3.msf控制台 4.远程工具RATS 5.远程访问计算机 6.白帽 二.技术基础 漏斗扫描工具AWVS AWVS简介 安装 ...

  4. Java基础之(四):使用IDEA实现HelloWorld

    使用IDEA实现HelloWorld 在使用IDEA这个集成开发环境写Java程序之前,我们要先对IDEA进行一些基本的配置,以便我们能够更好地使用它. 新建一个空项目,用来学习基础语法 设置项目名称 ...

  5. 洛谷1429 平面最近点对(KDTree)

    qwq(明明可以直接分治过掉的) 但是还是当作联系了 首先,对于这种点的题,很显然的套路,我们要维护一个子树\(mx[i],mn[i]\)分别表示每个维度的最大值和最小值 (这里有一个要注意的东西!就 ...

  6. 洛谷T31018 经典题丶改(LCT+离线)

    真的是一个大好题啊! QWQ首先我们考虑这种问题,如果直接在线做,估计应该是做不了,那我们是不是可以直接考虑离线. 将所有询问都按照\(r\)来排序. 然后依次加入每条边,计算\(a[i]<=n ...

  7. java设计模式_单例模式

    懒汉式 非线程安全 特点:Lazy 初始化.非多线程安全.易实现 描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程.因为没有加锁 synchronized,所以严格意义上它并不算单 ...

  8. Python&Selenium 数据驱动测试【unittest+ddt+xml】

    一.摘要 本博文将介绍Python和Selenium做自动化测试时,基于unittest框架,借助ddt模块,使用xml文件作为测试输入. 二.xml文件 保存路径:D:\\Programs\\Pyt ...

  9. CAM 模板样式表

    视图 模板类型 模板子类型 类型 子类型 刀具类型 刀具子类型 加工工序 mill_planar FACE_MILLING_AREA 100 261     加工工序 mill_planar FACE ...

  10. 机器学习:EM算法

    EM算法 各类估计 最大似然估计 Maximum Likelihood Estimation,最大似然估计,即利用已知的样本结果,反推最有可能(最大概率)导致这样结果的参数值的计算过程. 直白来讲,就 ...