def overlapping_lists(l0, l1): root0, root1 = has_cycle(l0), has_cycle(l1) if not root0 and not root1: return overlapping_no_cycle_lists(l0, l1) elif (not root0 and root1) or (root0 and not root1): return None # both lists have cycles: (1) disjoint cycles (2) starting nodes in cycles are the same # (3) starting nodes in cycles are different temp = root1 while True: temp = temp.next if temp is root0 or temp is root1: break if temp is not root0: return None # disjoint cycles def distance(s, t): dist = 0 while s is not t: dist += 1 s = s.next return dist length0, length1 = distance(l0, root0), distance(l1, root1) if length0 > length1: l0, l1 = l1, l0 root0, root1 = root1, root0 for i in range(abs(length0 - length1)): l1 = l1.next while l0 is not l1 and l0 is not root0 and l1 is not root1: l0, l1 = l0.next, l1.next return l0 if l0 is l1 else root0
def overlapping_lists(l0, l1): root0, root1 = has_cycle(l0), has_cycle(l1) if not root0 and not root1: return overlapping_no_cycle_lists(l0, l1) elif (root0 and not root1) or (not root0 and root1): return None temp = root1 while True: temp = temp.next if temp is root0 or temp is root1: break if temp is not root0: return None def distance(a, b): dis = 0 while a is not b: a = a.next dis += 1 return dis stem0_length, stem1_length = distance(l0, root0), distance(l1, root1) if stem0_length > stem1_length: l1, l0 = l0, l1 root0, root1 = root1, root0 for _ in range(abs(stem0_length - stem1_length)): l1 = l1.next while l0 is not l1 and l0 is not root0 and l1 is not root1: l0, l1 = l0.next, l1.next return l0 if l0 is l1 else root0
def overlapping_lists(l0, l1): # Store the start of cycle if any. root0, root1 = has_cycle(l0), has_cycle(l1) if not root0 and not root1: # Both lists don't have cycles. return overlapping_no_cycle_lists(l0, l1) elif (root0 and not root1) or (not root0 and root1): # One list has cycle, one list has no cycle. return None # Both lists have cycles. temp = root1 while True: temp = temp.next if temp is root0 or temp is root1: break # l0 and l1 do not end in the same cycle. if temp is not root0: return None # Cycles are disjoint. # Calculates the distance between a and b. def distance(a, b): dis = 0 while a is not b: a = a.next dis += 1 return dis # l0 and l1 end in the same cycle, locate the overlapping node if they # first overlap before cycle starts. stem0_length, stem1_length = distance(l0, root0), distance(l1, root1) if stem0_length > stem1_length: l1, l0 = l0, l1 root0, root1 = root1, root0 for _ in range(abs(stem0_length - stem1_length)): l1 = l1.next while l0 is not l1 and l0 is not root0 and l1 is not root1: l0, l1 = l0.next, l1.next # If l0 == l1 before reaching root0, it means the overlap first occurs # before the cycle starts; otherwise, the first overlapping node is not # unique, we can return any node on the cycle. return l0 if l0 is l1 else root0
def overlapping_lists(l0, l1): # TODO - you fill in here. root0 = has_cycle(l0) root1 = has_cycle(l1) if not root0 and not root1: return overlapping_no_cycle_lists(l0, l1) elif (root0 and not root1) or (root1 and not root0): return None runner = root1 while True: runner = runner.next if runner is root0 or runner is root1: break if runner is not root0: return None def distance(a, b): dis = 0 while a is not b: a = a.next dis += 1 return dis stem_length0 = distance(l0, root0) stem_length1 = distance(l1, root1) # make sure that root0 comes first if stem_length0 > stem_length1: l0, l1 = l1, l0 root0, root1 = root1, root0 for _ in range(abs(stem_length0 - stem_length1)): l1 = l1.next while l0 is not l1 and l0 is not root0 and l1 is not root1: l0 = l0.next l1 = l1.next if l0 is l1: return l0 else: return root1
def overlapping_lists(l0: ListNode, l1: ListNode) -> Optional[ListNode]: # Store the start of cycle if any. root0, root1 = has_cycle(l0), has_cycle(l1) if not root0 and not root1: # Both lists don't have cycles. return overlapping_no_cycle_lists(l0, l1) elif (root0 and not root1) or (not root0 and root1): # One list has cycle, one list has no cycle. return None # Both lists have cycles. temp = root1 while temp: temp = temp.next if temp is root0 or temp is root1: break return root1 if temp is root0 else None
def overlapping_lists(l0: ListNode, l1: ListNode) -> Optional[ListNode]: # TODO - you fill in here. t0, t1 = has_cycle(l0), has_cycle(l1) #neither list is cyclic if not t0 and not t1: return overlapping_no_cycle_lists(l1, l0) #one list is cyclic elif (t0 and not t1) or (t1 and not t0): return None #both lists are cyclic temp = t1 while temp: temp = temp.next if temp is t0 or temp is t1: break return t1 if temp is t0 else None
def overlapping_lists(l0: ListNode, l1: ListNode) -> Optional[ListNode]: def cycle_length(start): x, length = start, 0 while True: length += 1 x = x.next if x is start: return length x0, x1 = has_cycle(l0), has_cycle(l1) n_cyclic = (x0 is not None) + (x1 is not None) if n_cyclic == 0: return overlapping_no_cycle_lists(l0, l1) elif n_cyclic == 1: return None for _ in range(cycle_length(x0)): if x0 is x1: return x0 x0 = x0.next return None