题目一(判断无环单链表是否相交):
现在有两个无环单链表,若两个链表的长度分别为m和n,请设计一个时间复杂度为O(n + m),额外空间复杂度为O(1)的算法,判断这两个链表是否相交。
给定两个链表的头结点headA和headB,请返回一个bool值,代表这两个链表是否相交。保证两个链表长度小于等于500。
注意:对于单链表来说,只要一个点相交,那么因为next相同,所以之后的所有结点都相交
思路:
如果只判断是否相交,其实只需要判断最后一个结点是否相同即可。如果要求返回相交的第一个结点,那么我们需要先计算两个链表长度,然后从较长的那个链表开始向后移动,直到两链表剩下的相同,再逐一比较两个链表。比如链表1长100,链表2长50,我们先移动到链表1长50的的位置,然后与链表2一起一边向后移动一边比较
代码:
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
# 只判断是否相交
class CheckIntersect:
def chkIntersect(self, headA, headB):
# write code here
curA, curB = headA, headB
while curA.next:
curA = curA.next
while curB.next:
curB = curB.next
return curA == curB
# 需要返回相交的第一个结点
class CheckIntersect:
def chkIntersect(self, headA, headB):
# write code here
curA, curB = headA, headB
m, n = 0, 0
while curA or curB:
if curA:
m += 1
curA = curA.next
if curB:
n += 1
curB = curB.next
curA, curB = headA, headB
if m > n:
for i in range(m-n):
curA = curA.next
else:
for i in range(m-n):
curB = curB.next
while curA and curB:
if curA == curB:
return curA
curA = curA.next
curB = curB.next
return None
题目二(判断有环单链表是否相交):
如何判断两个有环单链表是否相交?相交的话返回第一个相交的节点,不想交的话返回空。如果两个链表长度分别为N和M,请做到时间复杂度O(N+M),额外空间复杂度O(1)。
给定两个链表的头结点head1和head2(注意,另外两个参数adjust0和adjust1用于调整数据,与本题求解无关)。请返回一个bool值代表它们是否相交。
思路:
判断链表是否有环可见:链表-5.12 判断链表是否有环_Iamlzm的博客-优快云博客
对于这题来说,首先应该找到两个链表的环入口,分别记为enter1,enter2。假设enter1 is enter2,那么说明两个链处于如下状态:
如果enter1 is not enter2,那么两个链表可能不相交,也可能处于如下状态:
代码:
class ChkIntersection:
def chkInter(self, head1, head2, adjust0, adjust1):
# write code here
enter1, enter2 = self.ringenter(head1), self.ringenter(head2)
# print(enter1.val, enter2.val)
if head1 is head2: #情况1:环入口相同
return True
cur = enter1
while True:
cur = cur.next
#情况2或3:在环内绕一圈,如果回到原点,说明两环不相交;否则说明环相交
if cur is enter1 or cur is enter2:
break
return cur is enter2
def ringenter(self, head): #寻找环入口结点
fast, slow = head, head
while True:
fast = fast.next.next
slow = slow.next
if fast is slow:
break
slow = head
while slow is not fast:
slow = slow.next
fast = fast.next
return slow
题目三(两单链表是否有交点):
给定两个单链表的头节点head1和head2,如何判断两个链表是否相交?相交的话返回true,不想交的话返回false。
给定两个链表的头结点head1和head2(注意,另外两个参数adjust0和adjust1用于调整数据,与本题求解无关)。请返回一个bool值代表它们是否相交。
思路:
其实就是前面的综合。首先需要判断:
- 如果一个无环,一个有环,那么肯定不相交
- 如果都无环,那么按照判断无环单链表是否相交的方法去判断
- 如果都有环,那么按照判断有环单链表是否相交的方法去判断
代码:
class ChkIntersection:
def chkInter(self, head1, head2, adjust0, adjust1):
# write code here
enter1, enter2 = self.ringenter(head1), self.ringenter(head2)
# 一个有环一个无环
if (enter1 and not enter2) or (not enter1 and enter2):
return False
# 都无环
elif not enter1 and not enter2:
curA, curB = head1, head2
while curA:
curA = curA.next
while curB:
curB = curB.next
return curA is curB
# 都有环
else:
if head1 is head2:
return True
cur = enter1
while True:
cur = cur.next
if cur is enter1 or cur is enter2:
break
return cur is enter2
def ringenter(self, head):
fast, slow = head, head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if fast is slow:
break
if not fast.next:
return None
slow = head
while slow is not fast:
slow = slow.next
fast = fast.next
return slow