链表专题 (III):环状链表的实现 + Leetcode 141 环形链表 + Leetcode 142 环形链表 II
环状链表的实现
首先,先创建一个根据列表以及 pos
这个参数实现环状链表的代码,是在:Python 面向对象编程 + 基本数据结构实现:链表、跳表、二叉树(施工中) 这篇文章中的实现的一个扩展。
代码如下:
class SingleLinkList(object):
def __init__(self, node = None):
self.head = node
def construct(self, nums, pos):
if not nums:
return None
else:
for i in range(0, len(nums)):
if i == 0:
cur = ListNode(nums[i])
self.head = cur
else:
node = ListNode(nums[i])
cur.next = node
cur = cur.next
tail = cur
if pos >= 0:
cur = self.head
for i in range(0, pos):
cur = cur.next
tail.next = cur
Leetcode 141 环形链表
题目描述
给定一个链表,判断链表中是否有环。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
题解
经典的实现方法是由一个快指针一个慢指针实现的:
- 快指针每次走两步
- 慢指针每次走一步。
- 重复1,2步。如果快指针的下一个节点是空,输出
False
;如果快指针与慢指针地址相同,则输出True
。
代码如下:
class Solution(object):
def hasCycle(self, head):
if not head:
return False
# 慢指针
cur1 = head
# 快指针
cur2 = head
while True:
if cur2.next:
if cur2.next.next:
cur2 = cur2.next.next
else:
return False
else:
return False
cur1 = cur1.next
if cur1 == cur2:
return True
执行结果
执行时间:36 ms
内存消耗:18.2 MB
Leetcode 142 环形链表 II
题目描述
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。
题解
每经过一个节点:如果节点不在集合中存储进一个集合 lst
中;如果这个点在集合中,则说明成环,输出这个节点。
如果走到后续节点为 None
的时候,说明不成环,输出 None
。
因为集合是按哈希表存储的,查询时间为 O ( 1 ) O(1) O(1) 。整个时间复杂度为 O ( N ) O(N) O(N) 。
代码如下:
class Solution(object):
def detectCycle(self, head):
if not head:
return None
cur = head
lst = set()
while cur:
if cur in lst:
return cur
lst.add(cur)
cur = cur.next
return None
执行结果
执行时间:48 ms
内存消耗:18.7 MB