Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from typing import List, Union, Collection, Mapping, Optional
from abc import ABC, abstractmethod

# Definition for singly-linked list.
class ListNode:
def __init__(self, x):
self.val = x
self.next = None

class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
"""
Floyd's Cycle Detection Algorithm (Two Pointers - Slow and Fast)

Time Complexity: O(n) where n is the number of nodes
Space Complexity: O(1) - only using two pointers
"""
if not head or not head.next:
return False

slow = head
fast = head

while fast and fast.next:
slow = slow.next
fast = fast.next.next

# If slow and fast meet, there's a cycle
if slow == fast:
return True

return False
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
class ListNode {
val: number
next: ListNode | null
constructor(val?: number, next?: ListNode | null) {
this.val = (val===undefined ? 0 : val)
this.next = (next===undefined ? null : next)
}
}


function hasCycle(head: ListNode | null): boolean {
/**
* Floyd's Cycle Detection Algorithm (Two Pointers - Slow and Fast)
*
* Time Complexity: O(n) where n is the number of nodes
* Space Complexity: O(1) - only using two pointers
*/
if (!head || !head.next) {
return false;
}

let slow: ListNode | null = head;
let fast: ListNode | null = head;

while (fast && fast.next) {
slow = slow!.next;
fast = fast.next.next;

// If slow and fast meet, there's a cycle
if (slow === fast) {
return true;
}
}

return false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import unittest
from src.my_project.interviews.top_150_questions_round_22\
.ex_55_linked_list_cycle import Solution, ListNode

class LinkedListTestCase(unittest.TestCase):

def create_linked_list_with_cycle(self, values, pos):
"""
Helper function to create a linked list with a cycle.

:param values: List of node values
:param pos: Index where tail connects (-1 means no cycle)
:return: Head of the linked list
"""
if not values:
return None

# Create all nodes
nodes = [ListNode(val) for val in values]

# Link nodes in sequence
for i in range(len(nodes) - 1):
nodes[i].next = nodes[i + 1]

# Create cycle if pos is valid
if pos >= 0 and pos < len(nodes):
nodes[-1].next = nodes[pos]

return nodes[0]

def test_first_pattern(self):
# Input: head = [3,2,0,-4], pos = 1
# Output: true
solution = Solution()
head = self.create_linked_list_with_cycle([3, 2, 0, -4], 1)
output = solution.hasCycle(head)
target = True
self.assertEqual(output, target)

def test_second_pattern(self):
# Input: head = [1,2], pos = 0
# Output: true
solution = Solution()
head = self.create_linked_list_with_cycle([1, 2], 0)
output = solution.hasCycle(head)
target = True
self.assertEqual(output, target)

def test_third_pattern(self):
# Input: head = [1], pos = -1
# Output: false
solution = Solution()
head = self.create_linked_list_with_cycle([1], -1)
output = solution.hasCycle(head)
target = False
self.assertEqual(output, target)