LeetCode如何求两个链表的第一个公共节点

这篇文章主要介绍LeetCode如何求两个链表的第一个公共节点,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

题目描述

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

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

               

题目样例

               

示例

LeetCode如何求两个链表的第一个公共节点

  • 输入: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 个节点。

               

题目思考

  1. 如何做到仅用 O(1) 内存得出结果?

               

解决方案

               

思路
  • 一个比较容易想到的思路是先遍历其中一个链表, 将节点存入集合中, 然后遍历另一个链表, 查看节点是否存在于集合中, 存在则说明找到. 这样虽然时间复杂度是 O(N), 但空间复杂度也是 O(N), 不满足题目要求
  • 重新观察题目示例, 假设链表 A 和 B 的共享部分长度为 shared, 各自前面独占部分长度为 a 和 b, 那么 A 的总长度为 a+shared, B 的总长度为 b+shared
  • 根据交换律, A+B 的长度等于 B+A 的长度, 也即 a+shared+b+shared == b+shared+a+shared
  • 根据上面这个式子, 我们可以定义两个指针, 分别从 A 和 B 的开头出发, 达到终点后换成另一个链表的起点继续走: 如果 A 和 B 有交点的话, 很显然两个指针会在交点处碰面, 共同走完剩余的 shared 部分; 而如果没交点的话, 两个指针只可能共同走到最后的空节点, 此时就返回 null
  • 特别注意一点, 我们遍历到最后一个节点的时候, 不能直接跳到开头, 而是应该先到末尾后面的空节点, 然后再跳到另一个链表的开头. 因为如果不进入空节点的话, 对于没有交点的情况就永远不可能跳出循环了(永远走不到末尾之后的空节点, 两个指针对应节点永远不可能相等)

               

复杂度
  • 时间复杂度 O(N): 只需要遍历两遍
  • 空间复杂度 O(1): 只定义了几个变量

               

代码
class Solution:
    def getIntersectionNode(self, headA: ListNode,
                            headB: ListNode) -> ListNode:
        a, b = headA, headB
        while a != b:
            # a如果到达A的末尾之后的空节点, 就置为B的起点重新遍历
            a = headB if not a else a.next
            # b如果到达B的末尾之后的空节点, 就置为A的起点重新遍历
            b = headA if not b else b.next
        return a

以上是“LeetCode如何求两个链表的第一个公共节点”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/223519.html

(0)
上一篇 2022年1月7日
下一篇 2022年1月7日

相关推荐

发表回复

登录后才能评论