From 6a68c343f5eb296edb4ad092fdb5ad62d85985a8 Mon Sep 17 00:00:00 2001 From: ganavi Date: Sun, 1 Nov 2026 16:43:50 +0530 Subject: [PATCH 1/2] Optimize Node.has_loop to use constant auxiliary space (Fixes #15576) --- data_structures/linked_list/has_loop.py | 74 +++++-------------------- 1 file changed, 15 insertions(+), 59 deletions(-) diff --git a/data_structures/linked_list/has_loop.py b/data_structures/linked_list/has_loop.py index a25204e3c4ce..54e127c9afdc 100644 --- a/data_structures/linked_list/has_loop.py +++ b/data_structures/linked_list/has_loop.py @@ -1,63 +1,19 @@ -from __future__ import annotations - -from collections.abc import Iterator -from typing import Any - - -class ContainsLoopError(Exception): - pass - - -class Node: - def __init__(self, data: Any) -> None: - self.data: Any = data - self.next_node: Node | None = None - - def __iter__(self) -> Iterator[Any]: - node = self - visited = set() - while node: - if node in visited: - raise ContainsLoopError - visited.add(node) - yield node.data - node = node.next_node - - @property - def has_loop(self) -> bool: - """ - A loop is when the exact same Node appears more than once in a linked list. - >>> root_node = Node(1) - >>> root_node.next_node = Node(2) - >>> root_node.next_node.next_node = Node(3) - >>> root_node.next_node.next_node.next_node = Node(4) - >>> root_node.has_loop - False - >>> root_node.next_node.next_node.next_node = root_node.next_node - >>> root_node.has_loop - True +@property +def has_loop(self) -> bool: """ - try: - list(self) - return False - except ContainsLoopError: - return True + Detect whether the linked list contains a cycle using Floyd's + Cycle-Finding Algorithm (Tortoise and Hare). + Time Complexity: O(n) + Auxiliary Space: O(1) + """ + slow = self + fast = self.next -if __name__ == "__main__": - root_node = Node(1) - root_node.next_node = Node(2) - root_node.next_node.next_node = Node(3) - root_node.next_node.next_node.next_node = Node(4) - print(root_node.has_loop) # False - root_node.next_node.next_node.next_node = root_node.next_node - print(root_node.has_loop) # True - - root_node = Node(5) - root_node.next_node = Node(6) - root_node.next_node.next_node = Node(5) - root_node.next_node.next_node.next_node = Node(6) - print(root_node.has_loop) # False + while fast is not None and fast.next is not None: + if slow is fast: + return True + slow = slow.next + fast = fast.next.next - root_node = Node(1) - print(root_node.has_loop) # False + return False \ No newline at end of file From 1fd7a6ea043d7c1d6382f84e8f2cde41d51eaca9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 1 Nov 2026 11:37:04 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- data_structures/linked_list/has_loop.py | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/data_structures/linked_list/has_loop.py b/data_structures/linked_list/has_loop.py index 54e127c9afdc..e5e72c4f628d 100644 --- a/data_structures/linked_list/has_loop.py +++ b/data_structures/linked_list/has_loop.py @@ -1,19 +1,19 @@ @property def has_loop(self) -> bool: - """ - Detect whether the linked list contains a cycle using Floyd's - Cycle-Finding Algorithm (Tortoise and Hare). + """ + Detect whether the linked list contains a cycle using Floyd's + Cycle-Finding Algorithm (Tortoise and Hare). - Time Complexity: O(n) - Auxiliary Space: O(1) - """ - slow = self - fast = self.next + Time Complexity: O(n) + Auxiliary Space: O(1) + """ + slow = self + fast = self.next - while fast is not None and fast.next is not None: - if slow is fast: - return True - slow = slow.next - fast = fast.next.next + while fast is not None and fast.next is not None: + if slow is fast: + return True + slow = slow.next + fast = fast.next.next - return False \ No newline at end of file + return False