网站建设中一览二栏什么意思网站开发工具特点总结
2026/4/18 8:08:55 网站建设 项目流程
网站建设中一览二栏什么意思,网站开发工具特点总结,重庆能创科技有限公司,网站如何不让百度抓取Java版LeetCode热题100之相交链表#xff1a;从哈希到双指针的深度解析 本文全面剖析 LeetCode 第160题「相交链表」#xff0c;涵盖题目理解、多种解法实现、复杂度分析、面试技巧及实际应用场景。无论你是准备面试的新手#xff0c;还是希望深入理解链表操作的老手#x…Java版LeetCode热题100之相交链表从哈希到双指针的深度解析本文全面剖析 LeetCode 第160题「相交链表」涵盖题目理解、多种解法实现、复杂度分析、面试技巧及实际应用场景。无论你是准备面试的新手还是希望深入理解链表操作的老手都能从中获得系统性提升。一、原题回顾题目编号LeetCode 160题目名称相交链表Intersection of Two Linked Lists难度等级简单Easy但极具启发性题目描述给你两个单链表的头节点headA和headB请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点返回null。关键约束题目数据保证整个链式结构中不存在环函数返回结果后链表必须保持其原始结构相交意味着内存地址相同而非值相同示例说明示例 1输入 intersectVal 8, listA [4,1,8,4,5], listB [5,6,1,8,4,5], skipA 2, skipB 3 输出Intersected at 8图示解释链表A: 4 → 1 ↘ 8 → 4 → 5 链表B: 5 → 6 → 1 ↗注意虽然两个链表都有值为1的节点但它们是不同的对象内存地址不同。只有值为8的节点是同一个对象。示例 2输入 intersectVal 2, listA [1,9,1,2,4], listB [3,2,4], skipA 3, skipB 1 输出Intersected at 2示例 3输入 intersectVal 0, listA [2,6,4], listB [1,5], skipA 3, skipB 2 输出No intersection约束条件1 m, n 3 * 10⁴链表长度1 Node.val 10⁵如果不相交intersectVal 0进阶要求时间复杂度 O(m n)空间复杂度 O(1)二、原题分析这道题的核心在于理解链表相交的本质 关键洞察相交 ≠ 值相同必须是同一个内存地址的节点Y型结构一旦相交后续所有节点都共享形成Y字形无环保证简化了问题无需考虑循环检测结构保持不能修改原链表如不能反转、不能标记 解题目标找到第一个内存地址相同的节点即两个链表开始共享的部分。❌ 常见误区误区1比较节点值 → 错误可能有重复值但不同对象误区2从后往前找 → 单链表无法反向遍历误区3先对齐再比较 → 需要知道长度差但如何高效获取三、答案构思我们将构建两种主要解法逐步优化✅ 方法一哈希集合Hash Set思路存储链表A的所有节点遍历链表B查找优点直观易懂代码简单缺点需要额外 O(m) 空间✅ 方法二双指针Two Pointers⭐️思路利用路径长度相等的巧妙设计优点O(1) 空间满足进阶要求缺点思路较难想到需理解路径对齐原理下面详细展开两种方法。四、完整答案Java 实现方法一哈希集合importjava.util.HashSet;importjava.util.Set;publicclassSolution{publicListNodegetIntersectionNode(ListNodeheadA,ListNodeheadB){// 边界检查if(headAnull||headBnull){returnnull;}// 存储链表A的所有节点SetListNodevisitednewHashSet();ListNodecurrentheadA;while(current!null){visited.add(current);currentcurrent.next;}// 遍历链表B查找第一个在集合中的节点currentheadB;while(current!null){if(visited.contains(current)){returncurrent;// 找到相交节点}currentcurrent.next;}returnnull;// 无相交}}方法二双指针推荐解法publicclassSolution{publicListNodegetIntersectionNode(ListNodeheadA,ListNodeheadB){// 边界检查if(headAnull||headBnull){returnnull;}ListNodepAheadA;ListNodepBheadB;// 当两个指针相遇时停止while(pA!pB){// pA走完自己的路就走pB的路pA(pAnull)?headB:pA.next;// pB走完自己的路就走pA的路pB(pBnull)?headA:pB.next;}// 如果相交pA/pB指向相交节点// 如果不相交pA/pB都为nullreturnpA;}}核心思想指针A走的总路径lenA lenB指针B走的总路径lenB lenA路径长度相等必然在相交点或终点相遇五、代码分析方法一哈希集合优点逻辑清晰先存后查符合直觉易于调试可打印集合内容验证扩展性强可轻松修改为查找所有相交点缺点空间开销大最坏情况存储全部m个节点哈希冲突虽然Java的HashSet处理良好但理论上存在边界处理空链表检查必不可少利用Set的contains()方法高效查找方法二双指针优点空间最优仅用两个指针变量代码简洁核心逻辑仅5行优雅巧妙体现算法之美关键细节指针重置时机必须在pA null时重置而非pA.next null循环终止条件pA ! pB包含相交和不相交两种情况空指针处理当不相交时两指针最终都为null自然退出执行过程示例示例1初始: pA4, pB5 步骤1: pA1, pB6 步骤2: pA8, pB1 步骤3: pA4, pB8 步骤4: pA5, pB4 步骤5: pAnull, pB5 → pA重置为headB(5) 步骤6: pA6, pBnull → pB重置为headA(4) 步骤7: pA1, pB1 步骤8: pA8, pB8 → 相遇返回8六、时间复杂度和空间复杂度分析方法时间复杂度空间复杂度说明哈希集合O(m n)O(m)遍历A存入遍历B查找双指针O(m n)O(1)每个指针最多走 mn 步详细推导双指针相交情况设链表A独有部分长度为a链表B独有部分长度为b公共部分长度为c指针A路径a c b指针B路径b c a总步数a b c ≤ m n不相交情况指针A路径m n指针B路径n m总步数m n性能对比mn30000哈希集合60000次操作 30000个对象存储双指针60000次操作 2个指针变量在内存受限环境如嵌入式系统双指针优势明显七、问题解答FAQQ1为什么双指针方法能保证找到相交点答因为两个指针走的总路径长度相等。如果相交都在第(abc)步到达相交点如果不相交都在第(mn)步到达null这种路径对齐确保了必然相遇。Q2能否先计算长度差然后对齐再比较答完全可以这是另一种O(1)空间的解法publicListNodegetIntersectionNode(ListNodeheadA,ListNodeheadB){intlenAgetLength(headA),lenBgetLength(headB);// 让长链表先走差值步if(lenAlenB){for(inti0;ilenA-lenB;i){headAheadA.next;}}else{for(inti0;ilenB-lenA;i){headBheadB.next;}}// 同步遍历while(headA!nullheadB!null){if(headAheadB)returnheadA;headAheadA.next;headBheadB.next;}returnnull;}privateintgetLength(ListNodehead){intlength0;while(head!null){length;headhead.next;}returnlength;}优缺点对比优点逻辑更直观容易理解缺点需要三次遍历两次算长度一次找交点而双指针只需一次Q3如果链表有环还能用这些方法吗答不能直接使用需要先检测环再分类讨论两链表都无环 → 本题情况一个有环一个无环 → 不可能相交两链表都有环 → 相交点可能在环内或环外这会大大增加复杂度属于Hard级别问题。Q4为什么题目强调保持原始结构答防止作弊方案比如修改节点值做标记反转链表再比较添加临时指针字段这些都会破坏原始数据在实际系统中不可接受。八、优化思路1. 早期终止优化哈希法在存储链表A时如果发现某个节点的next为null且不在链表B的预期范围内可提前终止答不行因为我们不知道链表B的结构无法预判。2. 双指针的变种实现有人担心指针重置会导致无限循环其实不会每个指针最多重置一次总步数严格限制在 mn3. 并行化思考理论上可以并行遍历两个链表但在单线程环境下无意义且同步开销大。✅结论双指针已是理论最优解无需进一步优化。九、数据结构与算法基础知识点回顾1. 单链表基础节点结构valnext指针遍历操作从头到尾O(n)时间空间特性动态分配非连续内存2. 哈希表HashSet底层实现数组 链表/红黑树Java 8时间复杂度平均O(1)插入/查找空间开销需要存储所有元素3. 双指针技巧同向双指针快慢指针如环检测相向双指针从两端向中间如两数之和交叉双指针本题的路径交叉技巧4. 复杂度分析要点时间复杂度关注最坏情况下的操作次数空间复杂度只计算额外使用的空间不包括输入进阶要求O(1)空间通常意味着不能使用集合、栈、递归等5. 内存地址 vs 值比较 比较引用相等内存地址相同equals() 比较值相等可重写本题要求必须用比较节点引用十、面试官提问环节❓ 面试官为什么不用递归解决这个问题考察点对空间复杂度的理解回答递归会使用系统栈空间复杂度为O(max(m,n))不满足O(1)的要求。而且递归无法直接解决路径长度不同的问题仍需要额外的长度计算。迭代方法更符合题目约束。❓ 面试官如果允许修改链表结构有什么更简单的办法考察点创造性思维回答可以采用标记法遍历链表A将每个节点的值设为特殊标记如负数遍历链表B找到第一个被标记的节点恢复链表A的原始值但这种方法破坏了保持原始结构的要求假设节点值可修改且有可用的标记值在多线程环境下不安全所以实际开发中不推荐。❓ 面试官你的双指针解法中如果两个链表完全相同不仅是相交会怎样考察点边界情况考虑回答如果两个链表完全相同即headA headB那么在第一次循环时就会发现pA pB直接返回headA。这是正确的因为相交点就是头节点。实际上这种情况是相交的特例独有部分长度为0。❓ 面试官能否用这个思路解决找链表中间节点的问题考察点知识迁移能力回答不能直接应用。找中间节点通常用快慢指针快指针走两步慢指针走一步这是另一种双指针技巧。本题的路径交叉思想适用于两个独立序列的对齐问题而快慢指针适用于单个序列的内部关系检测。不过两者都体现了通过指针移动策略解决遍历问题的核心思想。十一、这道算法题在实际开发中的应用1. Git版本控制系统分支合并不同分支的历史提交形成链表结构共同祖先查找类似找相交点确定合并基准实际实现Git使用更复杂的图算法但基本思想相似2. 内存泄漏检测对象引用链追踪对象的引用路径共享对象识别多个引用链指向同一对象时的检测工具实现如Java的VisualVM使用类似技术3. 数据库事务日志WALWrite-Ahead Logging事务日志形成链表检查点恢复多个日志流在某个点合并故障恢复需要找到最近的共同检查点4. 分布式系统一致性Raft协议日志复制形成链表结构Leader选举需要找到多数派的日志交集状态同步确定从哪个日志条目开始同步5. 编译器优化控制流图CFG基本块形成图结构支配节点分析找多个路径的共同祖先死代码消除识别不可达的代码路径核心价值在复杂的数据依赖关系中快速定位共同的交汇点这对于系统的一致性、恢复性和优化至关重要。十二、相关题目推荐题号题目关联点160. 相交链表本题链表相交检测141. 环形链表快慢指针检测环双指针基础142. 环形链表 II找环入口快慢指针进阶206. 反转链表链表基本操作指针操作练习234. 回文链表链表对称性双指针应用19. 删除链表的倒数第N个节点双指针间隔距离控制进阶挑战尝试解决[142. 环形链表 II]它结合了环检测和相交点查找的思想。十三、总结与延伸核心收获引用相等 vs 值相等在对象比较中要特别注意路径对齐思想通过巧妙的路径设计解决不对称问题空间复杂度意识O(1)空间往往需要更精巧的算法设计链表操作基础指针移动是链表问题的核心技能延伸思考多链表相交如果有k个链表如何找共同相交点可以两两合并时间复杂度O(k(mn))或使用最小堆维护k个指针动态相交检测如果链表在运行时动态变化需要维护额外的元数据或使用观察者模式概率算法能否用布隆过滤器近似解决可以但有误判率不适合精确场景最终建议面试首选双指针解法简洁、高效、体现算法思维务必理解原理不要死记硬背要能解释为什么有效手写无bug注意空指针检查和循环终止条件对比多种解法展示你的算法设计能力结语相交链表看似简单却蕴含着深刻的算法思想。从哈希的直观到双指针的巧妙每一步都是对问题本质的深入理解。掌握它你不仅解决了一道题更获得了解决路径对齐类问题的通用思维框架

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询