力扣 - 剑指 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 ...
随机推荐
- 【C++ Primer Plus】编程练习答案——第4章
1 void ch4_1() { 2 using namespace std; 3 string fname, lname; 4 char grade; 5 unsigned int age; 6 c ...
- java统一返回标准类型
一.前言.背景 在如今前后端分离的时代,后端已经由传统的返回view视图转变为返回json数据,此json数据可能包括返回状态.数据.信息等......因为程序猿的习惯不同所以返回json数据的格式也 ...
- Mysql 5.7版本,所有的坑,这里都有
MYSQL5.7版本流程的坑,我这里都有 必须按照如下操作.不按照下面操作,出错误不要怪我哦_ 我们首先在官网下载mysql5.7版本 解压之后,在bin相同目录下创建一个my.ini配置文件里面内容 ...
- 在Windows Server 2012R2离线安装.net framework3.5
最近新装了一台Windows Server 2012 R2的服务器,安装数据库时,出现了提示安装不上 .net framework3.5的情况,经过网络上多次的资料查找及反复试验终于找到了一个可以解决 ...
- Python读取网页表格数据
学会了从网格爬取数据,就可以告别从网站一页一页复制表格数据的时代了. 说个亲身经历的事: 以前我的本科毕业论文是关于"燃放烟花爆竹和空气质量"之间关系的,就要从环保局官网查资料. ...
- res目录下的结构
目录 res目录下的结构 drawable开头的文件夹 mipmap开头的文件夹 values开头的文件夹 layout文件夹 使用res目录下的资源 res目录下的结构 如果你展开res目录看一下, ...
- nginx搭建网站踩坑经历
为了更好的阅读体验,请访问我的个人博客 前言 早上刷抖音刷到一个只需要三步的nginx搭建教程(视频地址),觉得有些离谱,跟着复现了一遍,果然很多地方不严谨并且省略了大量步骤,对于很多不了解linux ...
- 4.19——数组双指针——26. 删除有序数组中的重复项 & 27. 删除有序数组中的重复项II & 80. 删除有序数组中的重复项 II
第一次做到数组双指针的题目是80: 因为python的List是可以用以下代码来删除元素的: del List[index] 所以当时的我直接用了暴力删除第三个重复元素的做法,大概代码如下: n = ...
- 前端HTML元素的类型名称
<div id="content" class="para" style="width:800px;"> <p>He ...
- Scrum Meeting 0607
零.说明 日期:2021-6-7 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 重新设计产品 ...