【LeetCode】剑指 Offer 52. 两个链表的第一个公共节点 p253 -- Java Version

news2024/10/6 19:19:27

题目链接:https://leetcode.cn/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/

1. 题目介绍(52. 两个链表的第一个公共节点)

输入两个链表,找出它们的第一个公共节点。
如下面的两个链表:
在这里插入图片描述
在节点 c1 开始相交。

【测试用例】:
示例 1:

在这里插入图片描述
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 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
输出:Reference of the node with value = 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。

【条件约束】:

提示

  • 如果两个链表没有交点,返回 null.
  • 在返回结果后,两个链表仍须保持原有的结构.
  • 可假定整个链表结构中没有循环.
  • 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存.

【相关题目】:

注意:本题与主站 160. 相交链表 题目相同.

2. 题解

2.1 枚举 – O(mn)

时间复杂度O(mn),空间复杂度O(1)

解题思路】:
枚举法:在第一个链表上顺序遍历每个节点,每遍历到一个节点,就在第二个链表上顺序比哪里每个节点。如果在第二个链表上有一个节点和第一个链表上的节点一样,则说明两个链表在这个节点上重合,于是就找到了它们的公共接待你。
……
实现策略】:

  1. 先进行无效输入判断;
  2. 创建一个临时节点 tmpB,用来保存链表 B 的头节点;
  3. 双重循环,找出在第二链表上第一个与第一链表相同的节点。
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
class Solution {
    // Solution1:枚举
    ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // 无效输入判断
        if (headA == null || headB == null) return null;
        // 保存 headB 的头节点
        ListNode tmpB = headB;
        // 循环判断 A 中的节点是否有和 B 中节点相同的
        while (headA != null) {
            // 让 headB 回到头节点上来
            headB = tmpB;
            while (headB != null) {
                if (headA == headB) return headA;
                // 不同的话,就让 B 移动到下一个节点
                headB = headB.next;
            }
            headA = headA.next;
        }
        // 两个链表没有公共节点,返回null
        return null;
    }
}

在这里插入图片描述

2.2 辅助栈 – O(m+n)

时间复杂度O(m+n),空间复杂度O(n)

解题思路】:
如果我们从两个链表的尾部开始往前比较,那么最后一个相同的节点就是我们要找的节点。我们可以通过栈来解决这个问题:分别把两个链表的节点放入两个栈里,这样两个链表的尾节点就位于两个栈的栈顶,接下来比较两个栈顶的节点是否相同。如果相同,则把栈顶弹出接着比较下一个栈顶,直到找到最后一个相同的节点。
……
实现策略】:

  1. 遍历两个链表,并分别将链表存入两个辅助栈中;
  2. 将两个辅助栈分别出栈,找出最后一个共同节点,该节点即为第一个公共节点
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
class Solution {
    // Solution2:辅助栈
    ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // 无效输入判断
        if (headA == null || headB == null) return null;

        // 定义两个辅助栈,用来分别存储链表 A 和 B
        Stack<ListNode> stackA = new Stack<>();
        Stack<ListNode> stackB = new Stack<>();

        // 遍历链表A,并将节点全部存入stackA
        while (headA != null) {
            stackA.push(headA);
            headA = headA.next;
        }
        // 遍历链表B,并将节点全部存入stackB
        while (headB != null) {
            stackB.push(headB);
            headB = headB.next;
        }

        ListNode pre = null;
        // 将两个辅助栈分别出栈,找出最后一个共同节点,该节点即为第一个公共节点
        while (!stackA.isEmpty() && !stackB.isEmpty()) {
            // 如果 A 和 B 当前的栈顶元素不同,则直接返回栈顶节点
            if (stackA.peek() != stackB.peek()) break;
            // 如果相同,则弹出
            pre = stackA.pop();
            stackB.pop(); 
        }


        // 两个链表没有公共节点,返回null
        return pre;
    }
}

在这里插入图片描述

2.3 双指针 – O(m+n)

时间复杂度O(m+n),空间复杂度O(1)
在这里插入图片描述

解题思路】:
我们使用两个指针 node1node2 分别指向两个链表 headAheadB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。
这样,当它们相遇时,所指向的结点就是第一个公共结点。
……
在这里插入图片描述
如上图所示:

  • headA 到首个公共节点的距离为 a-c
  • headB 到首个公共节点的距离为 b-c

……

  • 指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 首个公共节点 时,共走步数为 a+(b−c)
  • 指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 首个公共节点 时,共走步数为:b+(a−c)
  • 此时,我们就可以得到:a+(b−c)=b+(a−c)
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
class Solution {
    // Solution3:
    ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // 无效输入判断
        if (headA == null || headB == null) return null;
        ListNode A = headA, B = headB;
        while (A != B) {
            A = A != null ? A.next : headB;
            B = B != null ? B.next : headA;
        }
        
        // 两个链表没有公共节点,返回null
        return A;
    }
}

在这里插入图片描述

3. 参考资料

[1] 图解 双指针法,浪漫相遇
[2] 剑指 Offer 52. 两个链表的第一个公共节点(双指针,清晰图解)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于微信小程序开发的“校园帮”系统

基于微信小程序开发的“校园帮”系统【毕业论文&#xff0c;源码】 本系统使用了java和mysql结合的结构开发了微信小程序应用&#xff0c;系统中所有和数据库有关系的操作都通过一个通用类来实现&#xff0c;大大提高了代码的耦合性&#xff0c;当数据库类型等信息变化后直接修…

【剑指offer|6.寻找峰值】

0.寻找峰值 关键点: 返回任意一个峰值的下标即可nums[-1]nums[n]负无穷 输入&#xff1a;nums [1,2,3,1] 输出&#xff1a;2 解释&#xff1a;3 是峰值元素&#xff0c;你的函数应该返回其索引 2 1.傻瓜编程(纯属玩乐) class Solution { public:int findPeakElement(vector&l…

普通人在家就能用ChatGPT轻松月赚$5000美金的方法

太震撼了&#xff0c;这简直就是下个世纪才应该出现的产品&#xff0c;突然之间我感觉就像人类&#xff0c;刚刚发明了电灯一样&#xff0c;一切都要变了&#xff0c;而且变的速度太快&#xff0c;让我都觉得有点茫然了&#xff0c;绝对就是技术大爆炸。今天这篇文章我想通过ch…

React 的源码与原理解读(六):reconcileChildren 与 DIFF 算法

写在专栏开头&#xff08;叠甲&#xff09; 作者并不是前端技术专家&#xff0c;也只是一名喜欢学习新东西的前端技术小白&#xff0c;想要学习源码只是为了应付急转直下的前端行情和找工作的需要&#xff0c;这篇专栏是作者学习的过程中自己的思考和体会&#xff0c;也有很多参…

常年不卷,按时下班,工作能力强,同事求助知无不言,不扯皮,不拉帮结派,这样的职场清流竟然被裁掉了!...

在职场上&#xff0c;你永远想不到什么样的员工会被优化&#xff0c;比如下面这位&#xff1a;常年不卷&#xff0c;按时下班&#xff0c;工作很专业&#xff0c;同事问什么都回答&#xff0c;不扯皮&#xff0c;不拉帮结派&#xff0c;简直是职场清流。在上个月竟然被优化了&a…

一分钟腾讯云轻量应用服务器性能评测(慎入坑)

腾讯云轻量应用服务器性能评测&#xff0c;轻量服务器CPU主频、处理器型号、公网带宽、月流量、Ping值测速、磁盘IO读写及使用限制&#xff0c;轻量应用服务器CPU内存性能和标准型云服务器CVM处于同一水准&#xff0c;所以大家不要担心轻量应用服务器的性能&#xff0c;腾讯云百…

JavaEE企业级应用开发教程——第十章 初识Spring MVC框架(黑马程序员第二版)(SSM)

第十章 初识Spring MVC框架 JSP Model2架构模型是一种将页面显示、流程控制和业务逻辑分离的Web应用程序架构模型&#xff0c;采用JSP、Servlet和JavaBean技术实现。但是&#xff0c;它将通用逻辑以硬编码的方式实现&#xff0c;每次开发新的Web应用程序时都需要重新编写Servl…

MyBatis注解开发---实现增删查改和动态SQL

目录 1. 环境搭建 &#xff08;1&#xff09;创建持久层接口&#xff0c;并在接口方法上定义Sql语句 &#xff08;2&#xff09;测试方法 &#xff08;3&#xff09;运行结果 2. 注解实现增删查改 &#xff08;1&#xff09;增加用户 &#xff08;2&#xff09;删除用…

【4.17】贪心算法入门

什么是贪心&#xff1f; 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 刷题或者面试的时候&#xff0c;手动模拟一下感觉可以局部最优推出整体最优&#xff0c;而且想不到反例&#xff0c;那么就试一试贪心。 贪心的解题步骤&#xff1f; 贪心算法一…

《人体地图》笔记

《人体地图》 坂井建雄 著 孙浩 译 腹部通向大腿的隧道 腹部与大腿的分界点是大腿根部&#xff0c;即是腹股沟。 腹壁肌肉连结在腹股沟韧带上&#xff0c;腹壁肌肉包括三层&#xff0c;分别为腹外斜肌、腹内斜肌和腹横肌&#xff0c;每块肌肉都有一个张开的小孔&#xff0c;…

【靶场设计和渗透】

目录 一、前言 二、靶场设计 1、局域网 2、说明 三、渗透测试 1、信息收集 2、漏洞利用 四、后渗透利用 1、提权 2、权限维持 一、前言 为了深入贯彻学习网络安全法律法规&#xff0c;深入学习渗透测试知识&#xff0c;强化实战技能............ 编不出来了&#xff…

The Sandbox 的 OliveX Fitness 之城来啦!

4 月 11 日至 17 日&#xff0c;亲自来体验一下吧&#xff01; 这种独特的体验将有趣和故事驱动的游戏与健身以及奖励结合起来。玩家可以探索隐藏的角落&#xff0c;逃出迷宫&#xff0c;爬上梯子&#xff0c;清除障碍&#xff0c;完成相互关联的任务&#xff0c;所以战略规划是…

Avue dynamic表单实现form单选,修改及新增项

Avue dynamic表单实现form单选&#xff0c;修改及新增项 AvueDialogFormTableViewOption.js /** Description:银行账号* Version: 1.0* Autor: Tj* Date: 2023-03-21 11:02:42*/ export const BankAccountOption (vueObj, formData) > {return {labelWidth: 100, //整体列…

【华为OD机试】1046 - 计算字符串的编辑距离

文章目录一、题目&#x1f538;题目描述&#x1f538;输入输出&#x1f538;样例1二、思路解析三、代码参考作者&#xff1a;KJ.JK&#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f…

GDPU C语言 天码行空8

1. 求序列和 ⭐ 输出没有小数的浮点数 #include <stdio.h>double fun(int a, int n) {double res 0;int aa a,i;//aa 记录每一项for(i 1; i < n; i){res aa;aa aa * 10 a;}return res; }int main(){int a,n;scanf("%d %d", &a,&n);printf(&q…

Linux学习笔记——HTTPS协议

文章目录HTTPS是什么什么是加密为什么要进行加密常见的加密方式数据摘要与数据指纹数字签名HTTPS的工作过程探究方案1—只使对称加密方案2—只使非对称加密方案3—双方都是用非对称加密方案4—非对称加密对称加密中间人攻击证书方案5—非对称加密对称加密证书认证HTTPS是什么 H…

hypack单波束采集和处理基本流程

前两天有个读者问是否有单波束测深的操作和处理的步骤&#xff0c;在xiaok海洋测绘网上用关键字“单波束”搜索的结果就是确实没有相关的文章&#xff0c;相关的文章都是外业过程记录。下面以单波束XX&#xff08;可以是任何单波束&#xff09;和采集处理软件Hypack为例说明单波…

树莓派通过网线连接笔记本实现笔记本电脑Wifi的网络共享

基于windows电脑连接树莓派进行设置&#xff1a;通过通过一根网线&#xff0c;连接树莓派和电脑&#xff0c;使电脑和树莓派构成一个局域网&#xff0c;然后树莓派接收来自笔记本电脑wifi网络的共享网络。操作方法类似台式机通过网线共享笔记本电脑无线网络的步骤 1、 保证笔记…

[c++整人代码]超级加倍,让人承认自己是大傻猪

㊀程序介绍 这是本人看到的一个整人小病毒&#xff0c;唯一的杀伤力就是逼着你想坑的人承认他是猪。 本次更新&#xff1a;要求运行程序的人手动输入“我是猪”三个字 ㊁程序截图 1 本程序的窗口会自动保持最前 2 无法关闭本窗口 ㊂代码展示&#xff1a; #include <Wi…

【pinia持久化存储】使用pinia和pinia-plugin-persistedstate依赖进行数据的持久化存储

简言 使用pinia和pinia-plugin-persistedstate依赖进行数据的持久化存储。 存储方式 &#xff1a; localStoragesessionStorage pinia-plugin-persistedstate 中文官网 pinia 中文官网 安装 安装和使用 pinia &#xff0c;请参考使用pinia文章。 安装 pinia-plugin-pers…