算法通关村第一关—白银挑战—链表高频面试算法题—查找两个链表的第一个公共子节点

本文主要是介绍算法通关村第一关—白银挑战—链表高频面试算法题—查找两个链表的第一个公共子节点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 查找两个链表的第一个公共子节点
    • (1)暴力求解法
    • (2)使用哈希Hash⭐
    • (3)使用集合⭐ - 与Hash类似
    • (4)使用栈⭐
    • (5)仍有更多方法,作者尚未理解,理解会发出

查找两个链表的第一个公共子节点

  • 原题:Leetcode CR 171. 训练计划 V

题目说明:

输入两个链表,找出它们的第一个公共结点。

在这里插入图片描述
两个链表的头结点都是已知的,相交之后成为一个单链表,但是相交的位置未知,并且相交之前的结点数也是未知的,请设计算法找到两个链表的合并点


(1)暴力求解法

思路:通过冒泡的方式来遍历两个链表,将第一个链表中的每一个结点依次与第二个链表的每一个结点进行比较,当出现相同的结点指针,即为相交结点

注意:该方法虽然简单好理解,但是如果要考虑时间复杂度,暴力求解法一般都是最慢的,耗时最高的

/*** 1.暴力求解,循环遍历两个链表,判断结点相同* @param headA* @param headB* @return*/
public static ListNode findFirstCommonNodeByViolence(ListNode headA, ListNode headB) {// 每一个结点进行比较,判断是否相同ListNode A = headA;ListNode B = headB;while (A != null) {while (B != null) {if (A == B) {return A;}B = B.next;}B = headB;A = A.next;}return null;
}

(2)使用哈希Hash⭐

思路:将第一个链表的元素全部存入到HashMap里面,然后一边遍历第二个链表,一边检查当前元素是否在HashMap中

提示:Java中的Map包含containsKey等方法,可以检测该Map中是否包含该元素

在这里插入图片描述

 /*** 2.使用Hash的方法* @param headA* @param headB* @return*/
public static ListNode findFirstCommonNodeByMap(ListNode headA, ListNode headB) {Map<ListNode, Integer> hashMap = new HashMap<>();while (headA != null) {hashMap.put(headA, null); // 链表中的所有结点存入HashMap中headA = headA.next;}while (headB != null) {if (hashMap.containsKey(headB)) { // 判断HashMap中是否包含headB,包含说明找到了公共结点,直接返回即可return headB;}headB = headB.next;}return null;
}

(3)使用集合⭐ - 与Hash类似

思路:本质其实和哈希Hash没有太大区别,只是换了一个存储的空间,将所有的结点存入到集合中,然后一边遍历,一边检查当前元素是否在HashSet中

问题:为什么使用Set,而不使用其他集合,如List等等

解释:并不是说不可以使用List集合,相反可以使用List集合,也是可以的,但是List集合的运行时间和第一种暴力求解法没有什么区别,这是由于List集合是有序的,每次存进去其实还会需要记录一个相当于sort排序的值,它第几个进来的,这个也是会占用内存,导致运行时间变长,而Set集合是无序的,不需要记录一个sort值,因此使用Set的速度就快,并且我们追进HashSet的源码进去查看,可以发现HashSet其实就是new HashMap对象,也就是HashSet就是HashMap,跟哈希Hash是没有本质区别的

/*** 3.使用集合的方法* @param headA* @param headB* @return*/
public static ListNode findFirstCommonNodeBySet(ListNode headA, ListNode headB) {Set<ListNode> set = new HashSet<>();// 循环遍历head1,将head1所有元素存到set中while (headA != null) {set.add(headA);headA = headA.next;}// 循环遍历head2,判断set集合链表是否包含head2while (headB != null) {if (set.contains(headB)) {return headB;}headB = headB.next;}return null;
}

(4)使用栈⭐

思路:将两个链表分别存入到两个栈中,两边同时出栈,判断是否一致,如果一致则说明存在相交,那么我们就继续查找,直到不一致,说明相同的结点都已经出栈了,就已经找到了两个链表的公共结点

提示:栈是后进先出,存进去后相同的都在后面,因此相同的结点也就是存在栈顶

/*** 4.通过栈的方法* @param headA* @param headB* @return*/
public static ListNode findFirstCommonNodeByStack(ListNode headA, ListNode headB) {Stack<ListNode> stackA = new Stack();Stack<ListNode> stackB = new Stack();while (headA != null) {stackA.push(headA); // 存入栈中headA = headA.next;}while (headB != null) {stackB.push(headB); // 存入栈中headB = headB.next;}ListNode preNode = null;while (stackB.size() > 0 && stackA.size() > 0) {// 由于存是从头存到底部,因此后面的结点都是相同的,当取出来是不一样的时候,说明从公共结点分隔出去了,到分岔口了,那就直接break即可if (stackA.peek() == stackB.peek()) { // peek表示查看此堆栈顶部的对象,但是不会删除,而pop是直接返回了,也就删除了preNode = stackA.pop();stackB.pop();} else {break;}}return preNode;
}

(5)仍有更多方法,作者尚未理解,理解会发出

这篇关于算法通关村第一关—白银挑战—链表高频面试算法题—查找两个链表的第一个公共子节点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

C++链表的虚拟头节点实现细节及注意事项

《C++链表的虚拟头节点实现细节及注意事项》虚拟头节点是链表操作中极为实用的设计技巧,它通过在链表真实头部前添加一个特殊节点,有效简化边界条件处理,:本文主要介绍C++链表的虚拟头节点实现细节及注... 目录C++链表虚拟头节点(Dummy Head)一、虚拟头节点的本质与核心作用1. 定义2. 核心价值二

C++作用域和标识符查找规则详解

《C++作用域和标识符查找规则详解》在C++中,作用域(Scope)和标识符查找(IdentifierLookup)是理解代码行为的重要概念,本文将详细介绍这些规则,并通过实例来说明它们的工作原理,需... 目录作用域标识符查找规则1. 普通查找(Ordinary Lookup)2. 限定查找(Qualif

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

C#实现查找并删除PDF中的空白页面

《C#实现查找并删除PDF中的空白页面》PDF文件中的空白页并不少见,因为它们有可能是作者有意留下的,也有可能是在处理文档时不小心添加的,下面我们来看看如何使用Spire.PDFfor.NET通过C#... 目录安装 Spire.PDF for .NETC# 查找并删除 PDF 文档中的空白页C# 添加与删

Springboot实现推荐系统的协同过滤算法

《Springboot实现推荐系统的协同过滤算法》协同过滤算法是一种在推荐系统中广泛使用的算法,用于预测用户对物品(如商品、电影、音乐等)的偏好,从而实现个性化推荐,下面给大家介绍Springboot... 目录前言基本原理 算法分类 计算方法应用场景 代码实现 前言协同过滤算法(Collaborativ

数据库面试必备之MySQL中的乐观锁与悲观锁

《数据库面试必备之MySQL中的乐观锁与悲观锁》:本文主要介绍数据库面试必备之MySQL中乐观锁与悲观锁的相关资料,乐观锁适用于读多写少的场景,通过版本号检查避免冲突,而悲观锁适用于写多读少且对数... 目录一、引言二、乐观锁(一)原理(二)应用场景(三)示例代码三、悲观锁(一)原理(二)应用场景(三)示例