LeetCode 160题:寻找两个链表的交点(解法巧妙,且其数学原理应该掌握)

题目

Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:
在这里插入图片描述
begin to intersect at node c1.
Example 1:
在这里插入图片描述
Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
Output: Reference of the node with value = 8
Input Explanation: The intersected node’s value is 8 (note that this must not be 0 if the two lists intersect). From the head of A, it reads as [4,1,8,4,5]. From the head of B, it reads as [5,0,1,8,4,5]. There are 2 nodes before the intersected node in A; There are 3 nodes before the intersected node in B.
Example 2:
在这里插入图片描述
Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
Output: null
Input Explanation: From the head of A, it reads as [2,6,4]. From the head of B, it reads as [1,5]. Since the two lists do not intersect, intersectVal must be 0, while skipA and skipB can be arbitrary values.
Explanation: The two lists do not intersect, so return null.
注意:

  • 如果不相交,返回null
  • 不能改变输入链表
  • 你可以认为输入的链表中没有环路
  • 你的代码应该尽可能的实现时间复杂度O(n)以及空间复杂度O(1)

解法

常规的解法

依次遍历链表A和B,用集合sa和sb记录见过的节点,并判断是否相交.此种算法时间复杂度为O(n),但是空间复杂度较高.代码如下:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        na, nb, ni = headA, headB, None
        sa, sb = {na}, {nb}
        while na or nb:
            if na in sb:
                ni = na
                break
            if nb in sa:
                ni = nb
                break
                
            if na:
                na = na.next
                sa.add(na)
            if nb:
                nb = nb.next
                sb.add(nb)
                
        return ni

算法的结果如下:
Runtime: 188 ms, faster than 85.84% of Python online submissions for Intersection of Two Linked Lists.
Memory Usage: 42.9 MB, less than 5.33% of Python online submissions for Intersection of Two Linked Lists.

巧妙且应该掌握的解法

该解法由coordinate_blog进行了清晰的解释,我在这里记录一下.如下图,链表A和B都是由各自黑色的部分和共同的红色部分组成.
在这里插入图片描述
如果将链表拉直然后拼成A+B和B+A放在一起,就会成为下面这个样子:
在这里插入图片描述
最后的红色部分是对齐了的,所以我们就能在该出通过相等判断找到相交的位置.注意,没有相交的情况可以看做在节点None处(最末尾)相交了.代码如下:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def getIntersectionNode(self, headA, headB):
        """
        :type head1, head1: ListNode
        :rtype: ListNode
        """
        na, nb = headA, headB
        while na != nb:
            na = na.next if na else headB
            nb = nb.next if nb else headA
            
        return na

运行结果如下,好像并不是很优秀…:
Runtime: 184 ms, faster than 92.74% of Python online submissions for Intersection of Two Linked Lists.
Memory Usage: 41.8 MB, less than 37.33% of Python online submissions for Intersection of Two Linked Lists.

我将我写的LeetCode代码都记录在了GitHub,欢迎大家去逛逛

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章