单链表可能有环,也可能无环。给定两个单链表的头节点 head1 和 head2,这两个链表可能相交,也可能不相交。请实现一个函数,如果两个链表相交,请返回相交的第一个节点;如果不相交,返回null即可。
如果链表 1 的长度为 N,链表 2 的长度为 M,时间复杂度请达到 O(N+M),额外空间复杂度请达到 O(1)
•问题一:判断链表是否有环
• 设置一个慢指针和一个快指针。从链表头结点开始,慢指针一次走一步,
慢指针一次走两步• 如果链表无环,则快指针会移动到终点。
• 如果链表有环,则快指针和慢指针会相遇。相遇后令快指针回到头节点,接着快慢指针都一次走一步,两者再次相遇的节点就是入环节点
def getLoopNode(head):
if head == None or head.next == None or head.next.next == None:
return None
slow = head.next
fast = head.next.next
while slow != fast:
if fast.next == None or fast.next.next == None:
return None
slow = slow.next
fast = fast.next.next
fast = head
while slow != fast:
slow = slow.next
fast = fast.next
return slow
•问题二:判断两个无环链表是否相交
• 先分别遍历两个链表,得到两个链表的的长度:len1 和 len2
• 如果链表 1 更长,则链表 1 先走 len1 - len2 步;否则,链表 2 先走 len2 - len1 步
• 然后两个链表一起走,一次走一步,相遇的节点就是相交节点
def noLoop(head1, head2):
if head1 == None or head2 == None:
return None
cur1 = head1
cur2 = head2
n = 0
while cur1.next != None:
n += 1
cur1 = cur1.next
while cur2.next != None :
n -= 1
cur2 = cur2.next
if cur1 != cur2:
return None
cur1 = head1 if n >= 0 else head2
cur2 = head1 if cur1 == head2 else head2
n = abs(n)
while n != 0:
cur1 = cur1.next
n -= 1
while cur1 != cur2:
cur1 = cur1.next
cur2 = cur2.next
return cur1
•问题三:判断两个有环链表是否相交
• 先得到两个有环链表的入环节点 loopNode1 和 loopNode2
• 如果 loopNode1 == loopNode2,那 么两个链表必然相交(有公共的环), 而且相交节点必然位于入环节点之前 (包含入环节点)。入环之前的链表 部分没有环,所以求相交节点的方法 同问题二,只是将链表终点从 nullptr 换成了 loopNode1->next
如果 loopNode1 != loopNode2,那么两个链表可能相交也可能不相交,相交的情况也只可能发生在环节点中
从loopNode1开始绕圈遍历节点,再绕回到loopNode1之前如果遇到loopNode2,说明相交,返回 loopNode1或loopNode2都行,都算相交节点。如果绕回loopNode1的过程中一直没碰上loopNode2,说明不相交
def bothLoop(head1, node1, head2, node2):
if head1 == None or head2 == None:
return None
if node1 == node2:
cur1 = head1
cur2 = head2
n = 0
while cur1 != node1:
n += 1
cur1 = cur1.next
while cur2 != node1:
n -= 1
cur2 = cur2.next
cur1 = head1 if n >= 0 else head2
cur2 = head1 if cur1 == head2 else head2
n = abs(n)
while n != 0:
n -= 1
cur1 = cur1.next
while cur1 != cur2:
cur1 = cur1.next
cur2 = cur2.next
return cur1
else:
cur1 = node1.next
while cur1 != node1:
if cur1 == node2:
return node1
cur1 = cur1.next
return None
#主函数
class Node:
def __init__(self, val=None):
self.val = val
self.next = None
def getIntersectNode(head1, head2):
if head1 == None or head2 == None:
return None
node1 = getLoopNode(head1)
node2 = getLoopNode(head2)
if node1 == None and node2 == None:
return noLoop(head1, head2)
if node1 != None and node2 != None:
return bothNode(head1, node1, head2, node2)
return None