判断给定的链表中是否有环(不一定是首尾相连)
注意:
尽量不要申请额外空间
1:O(n)时间复杂度(参考:https://www.cnblogs.com/hiddenfox/p/3408931.html)
复杂度O(n)的方法,使用两个指针slow,fast。两个指针都从表头开始走,slow每次走一步,fast每次走两步,如果fast遇到null,则说明没有环,返回false;如果slow==fast,说明有环,并且此时fast超了slow一圈,返回true。
为什么有环的情况下二者一定会相遇呢?因为fast先进入环,在slow进入之后,如果把slow看作在前面,fast在后面每次循环都向slow靠近1,所以一定会相遇,而不会出现fast直接跳过slow的情况。
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head:
return False
pointer1 = head
pointer2 = head
while pointer1 is not None:
pointer1=pointer1.next #指针1加一
if not pointer2.next:
return False
pointer2 = pointer2.next #指针2加一
if not pointer2.next:
return False
pointer2 = pointer2.next #指针2再加一
if pointer2==pointer1:
return True
return False
2:O(n^2)的时间复杂度(错误:超出时间限制)(参考:https://www.cnblogs.com/hiddenfox/p/3408931.html)
复杂度O(n^2)的方法,使用两个指针a, b。a从表头开始一步一步往前走,遇到null则说明没有环,返回false;a每走一步,b从头开始走,如果遇到b==a.next,则说明有环true,如果遇到b==a,则说明暂时没有环,继续循环。
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head:
return False
pointer1 = head
pointer2 = head
while pointer1.next is not None: #挨个访问结点
while pointer2!=pointer1: #从头开始一直访问到Pointer1结点
if pointer2==pointer1.next:
return True
pointer2 = pointer2.next
if pointer2==pointer1.next: #防止链表最后一个结点自身成环
return True
pointer1=pointer1.next
pointer2=head
return False
3:新建一个列表,用于存放访问过的结点,判断下一个结点是否在列表中(错误:超出时间限制)
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head:
return False
tempNodeList = [head]
while head.next!=None and head.next not in tempNodeList:
head = head.next
tempNodeList.append(head)
if head.next == None:
return False
else:
return True