有环单链表,求环长、链长
这是一个关于单链表的经典例题。即,给定一个有环的单链表,求环长、链长等。或者,给定一个单链表,判断是否有环?
可以遍历这个链表,将每一个节点存入一个有顺序的集合,同时判断当前节点是否在这个集合中出现,从而判断该链表是否有环以及求环长与链长。当时空间复杂度与时间复杂度都过大了。
另一个经典方法就是快慢指针,即两个指针同时从链表头开始走,快指针一次走2步,慢指针一次走1步。于是

假设这个有环链表的join点之前的节点数为a,环长为n,两个指针相遇点距离表头距离为a+b。如上图,其中k表示快慢指针相遇的时候,快指针走过环的圈数。
那么,让快慢指针同时从表头出发,当它们相遇的时候,让慢指针回到表头,并让快指针的步长变为1。等到它们再次相遇的时候,相遇点即为链表环的join点。
原因如上图,快指针再走a个节点(此时每步走一个节点)就会到达join点,慢指针从表头开始走a个节点也会到达join点。
这样即可判断给定单链表是否有环。也能求解环长以及链长。
代码如下:
class Node:
def __init__(self, val):
self.val = val
self.next = None
def buildRingedLinkList(handleLen, ringLen):
head = Node(0)
temp = head
for i in range(1, handleLen+1):
temp.next = Node(i)
temp = temp.next
join = temp
for i in range(handleLen+1, handleLen+ringLen):
temp.next = Node(i)
temp = temp.next
temp.next = join
return head
def getJoinNode(linkList):
l1, l2 = linkList, linkList
while True:
if l2 is None:
return None
l1 = l1.next
l2 = l2.next.next
if l1 == l2:
break
l1 = linkList
while True:
l1 = l1.next
l2 = l2.next
if l1 == l2:
break
return l1
head = buildRingedLinkList(3, 5)
print(getJoinNode(head).val)
代码中,buildRingedLinkList方法用于构造有环单链表(代码中构造的有环单链表如下图),getJoinNode用于获取有环单链表的join点,如果无环则返回None。

求两链表的交点
对于两个链表存在一个交点的情况,即类似于“Y”形状的链表,求这个交点。
方法一:我们可以直接让其中一个链表首尾相连,即将这两个有交点的链表转化为有环单链表。于是可以直接采用求解有环单链表的解法求解。
方法二:首先分别遍历获得两个链表的长度,让指针l1l1l1在较长的链表上先走两个链表长度之差个节点,然后让指针l2l2l2在较短的链表上与指针l1l1l1同时走,并判断两个指针所指是否相同,若相同则找到了交点直接返回即可。
本文探讨了如何解决有环单链表的问题,包括判断链表是否存在环、求环长和链长。介绍了快慢指针的方法,以及如何找到两链表的交点。同时提供了两种解决两链表交点问题的策略:转换为有环链表求解和通过比较链表长度同步指针行走。

618

被折叠的 条评论
为什么被折叠?



