Leetcode 141 Linked List Cycle
题目描述
Given a linked list, determine if it has a cycle in it.
To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0
Output: true
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: false
Explanation: There is no cycle in the linked list.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/linked-list-cycle
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路解析
- 方案一:
利用列表,遍历整个链表,如果列表中不含有当前结点,则将当前结点添加到列表中,如果遍历过程中发现列表中已经含有当前结点,则可以判断该链表是含有环路的
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or head.next is None:
return False
temp = []
while head:
if head in temp:
return True
temp.append(head)
head = head.next
return False
(注意:不要用结点的值来判断是否遍历到同一个结点,这样会导致无法处理含有值相同的多个结点的链表)
但是上述的算法存在一个问题,外层的while循环时间复杂度为 O ( N ) , N 为 链 表 长 度 O(N),N为链表长度 O(N),N为链表长度,在内层的if语句判断temp是否含有某结点时,其时间复杂度为 O ( M ) , M 为 t e m p 的 当 前 长 度 O(M),M为temp的当前长度 O(M),M为temp的当前长度,整个算法的时间复杂度为 O ( M ∗ N ) O(M*N) O(M∗N),空间复杂度为 O ( N ) O(N) O(N)。显然是一个低效的算法.
我们可以对内层if语句进行改进,将列表改为hash表,哈希表判断是否含有某元素的时间复杂度 O ( 1 ) O(1) O(1)
- 方案一的改进:
将列表换为哈希表,可以直接使用python中的字典,提高查找效率。代码如下:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or head.next is None:
return False
temp = {}
while head:
if temp.get(head):
return True
temp[head] = 1
head = head.next
return False
速度噌的一下就上去了。时间复杂度为 O ( N ) O(N) O(N),空间复杂度为 O ( N ) O(N) O(N)
- 快慢指针法
慢指针每次走一步,快指针每次走两步,如果链表中存在环,快慢指针一定会相遇
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if not head or head.next is None:
return False
slow = head
fast = head.next
while slow != fast:
if fast and fast.next:
slow = slow.next
fast = fast.next.next
else:
return False
return True
时间复杂度为 O ( N + K ) , N 为 链 表 长 度 , K 为 环 路 部 分 长 度 O(N+K),N为链表长度,K为环路部分长度 O(N+K),N为链表长度,K为环路部分长度,空间复杂度为 O ( 1 ) O(1) O(1)。
需要证明快慢指针一定会相遇。