给你两个单链表的头节点headA和headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null。
图示两个链表在节点c1开始相交:
题目数据保证整个链式结构中不存在环。注意,函数返回结果后,链表必须保持其原始结构。
评测系统的输入如下(你设计的程序不适用此输入):
相交的起始节点的值。如果不存在相交节点,这一值为0第一个链表第二个链表在listA中(从头节点开始)跳到交叉节点的节点数在listB中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点headA和headB传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被视作正确答案。
二、示例2.1示例1:intersectVal=8,listA=[4,1,8,4,5],listB=[5,6,1,8,4,5],skipA=2,skipB=Intersectedat8相交节点的值为8(注意,如果两个链表相交则不能为0)。从各自的表头开始算起,链表A为[4,1,8,4,5],链表B为[5,6,1,8,4,5]。在A中,相交节点前有2个节点;在B中,相交节点前有个节点。请注意相交节点的值不为1,因为在链表A和链表B之中值为1的节点(A中第二个节点和B中第三个节点)是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表A和链表B中值为8的节点(A中第三个节点,B中第四个节点)在内存中指向相同的位置。
2.2示例2:intersectVal=0,listA=[2,6,4],listB=[1,5],skipA=,skipB=2null从各自的表头开始算起,链表A为[2,6,4],链表B为[1,5]。由于这两个链表不相交,所以intersectVal必须为0,而skipA和skipB可以是任意值。这两个链表不相交,因此返回null。
提示:listA中节点数目为m
listB中节点数目为n
1=m,n=*10^4
1=Node.val=10^5
0=skipA=m
0=skipB=n
如果listA和listB没有交点,intersectVal为0
如果listA和listB有交点,intersectVal==listA[skipA]==listB[skipB]
进阶:你能否设计一个时间复杂度O(m+n)、仅用O(1)内存的解决方案?
三、解题思路根据题目描述,我们要寻找两个链表的相交起始节点,那么这里我们需要明确一个问题,在链表中,怎么去定义相交这个概念?首先我们来看一下,下面的两种“相交”情况:
我们可以看到两个链表在节点6的位置处相交了,那么如果是这种链表相交的情况话,返回的结果但就是Node(6)这个节点了。我们可以看到两个链表在节点6的位置处相交了,但是又“分叉”出了两条链表,分别是:[7,9]和[8,10,11],这种情况其实是不能发生的。因为我们节点的数据结构是一个单向链表,即:节点中只有一个next指针,所以无法在Node(6)的后置节点中即指向Node(7)又指向Node(8);
所以,根据以上描述,我们只会关心情况1中的相交。那么“相交”的概念我们明确了之后,我们就来针对这道题,再深入的分析一下两条链表会发生哪些情况:
那么这种情况,就是我们可以获得相交节点的情况了,此处就不再赘述了。这种属于是两条平行链表了,那么它们永远不会相交,所以返回null就可以了。
针对链表相交的情况,我们可以见下图所示,创建两个指针p1和p2,分别指向两条链表的起止节点,我们假设无论p1还是p2都会遍历完两条链表,那么我们会发现,它们最终遍历的长度一定是相同的,即:会在某个遍历步骤下相遇;而因为我们将null也作为了一种节点,所以,当两条链表是平行的话,最终他们也都会指向null值这个虚拟节点上了。为了方便大家理解,这两种情况均在下图示例了出来,为了加深理解,请见下图所示:
四、代码实现publicclassSolution{publicListNodegetIntersectionNode(ListNodeheadA,ListNodeheadB){ListNodeap=headA,bp=headB;while(ap!=bp){ap=ap==null?headB:ap.next;bp=bp==null?headA:bp.next;}returnap;}}/***Definitionforsingly-linkedlist.*publicclassListNode{*intval;*ListNodenext;*ListNode(intx){*val=x;*next=null;*}*}*/
今天的文章内容就这些了:
写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的点赞分享。
更多技术干货,欢迎大家