环形链表Ⅰ
简单的版本,给定一个链表,判断链表中是否有环。
解法一:判重法
借助 set 这个数据结构进行判重,每遍历链表的一个节点,就将这个节点的元素加入 set 中,如果链表有环的话,那么肯定有一个元素会被访问两次,当第二次访问这个元素的时候,set中就会找到这个元素对应的记录了,这样就可以判断出链表是否有环了。
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
s = set() # 定义一个set辅助判重,然后不断遍历链表
while head:
if head in s: # 如果遍历到某个节点已经在 set中,说明遍历到重复节点了,也就是有环
return True
s.add(head) # 每遍历到一个新节点,就添加到 set中
head = head.next
return False
另外,我们也可以借助 dict 来实现判重。
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
dic = {} # 定义一个哈希表
while head:
if head in dic: # 遍历到重复节点,说明有环
return True
dic[head] = 1 # 否则将该元素在哈希表中对应的值设为1
head = head.next
return False
解法二:快慢指针
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if head == None or head.next == None: # 如果链表为空,或者只有一个 next指向空的节点,则肯定无环
return False
slow = fast = head # 快慢指针均初始化为指向头节点
while fast and fast.next: # 遍历链表直到fast跳到了链表外(fast为空),或跳到最后一个节点(下一次无法再跳到fast.next.next了)
slow = slow.next # 慢指针每次走一步
fast = fast.next.next # 快指针每次走两步
if slow == fast: # 如果快慢指针相遇,说明有环
return True
return False # 直到遍历完都不相遇则无环
环形链表Ⅱ
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
解法二:快慢指针
先同前面的采用快慢双指针检测是否存在环,如果两个指针相遇了,说明有环,则一个指针重新指向 head,一个保持在原有位置上,速度均改为1,然后继续移动双指针,直到再次相遇时,相遇点即为入环的节点。
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
slow = fast = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast: # 相遇说明有环
slow = head # slow重新指向 head,fast不变
while slow is not fast: # 双指针速度均改为1,继续移动,直到再次相遇
slow = slow.next
fast = fast.next
return slow
return None