Skip to content

Commit dd4894f

Browse files
authored
Merge pull request #1523 from ivanpenaloza/january21
adding algo
2 parents d607148 + 589c5c2 commit dd4894f

3 files changed

Lines changed: 124 additions & 0 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from typing import List, Union, Collection, Mapping, Optional
2+
from abc import ABC, abstractmethod
3+
4+
# Definition for singly-linked list.
5+
class ListNode:
6+
def __init__(self, x):
7+
self.val = x
8+
self.next = None
9+
10+
class Solution:
11+
def hasCycle(self, head: Optional[ListNode]) -> bool:
12+
"""
13+
Floyd's Cycle Detection Algorithm (Two Pointers - Slow and Fast)
14+
15+
Time Complexity: O(n) where n is the number of nodes
16+
Space Complexity: O(1) - only using two pointers
17+
"""
18+
if not head or not head.next:
19+
return False
20+
21+
slow = head
22+
fast = head
23+
24+
while fast and fast.next:
25+
slow = slow.next
26+
fast = fast.next.next
27+
28+
# If slow and fast meet, there's a cycle
29+
if slow == fast:
30+
return True
31+
32+
return False
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class ListNode {
2+
val: number
3+
next: ListNode | null
4+
constructor(val?: number, next?: ListNode | null) {
5+
this.val = (val===undefined ? 0 : val)
6+
this.next = (next===undefined ? null : next)
7+
}
8+
}
9+
10+
11+
function hasCycle(head: ListNode | null): boolean {
12+
/**
13+
* Floyd's Cycle Detection Algorithm (Two Pointers - Slow and Fast)
14+
*
15+
* Time Complexity: O(n) where n is the number of nodes
16+
* Space Complexity: O(1) - only using two pointers
17+
*/
18+
if (!head || !head.next) {
19+
return false;
20+
}
21+
22+
let slow: ListNode | null = head;
23+
let fast: ListNode | null = head;
24+
25+
while (fast && fast.next) {
26+
slow = slow!.next;
27+
fast = fast.next.next;
28+
29+
// If slow and fast meet, there's a cycle
30+
if (slow === fast) {
31+
return true;
32+
}
33+
}
34+
35+
return false;
36+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import unittest
2+
from src.my_project.interviews.top_150_questions_round_22\
3+
.ex_55_linked_list_cycle import Solution, ListNode
4+
5+
class LinkedListTestCase(unittest.TestCase):
6+
7+
def create_linked_list_with_cycle(self, values, pos):
8+
"""
9+
Helper function to create a linked list with a cycle.
10+
11+
:param values: List of node values
12+
:param pos: Index where tail connects (-1 means no cycle)
13+
:return: Head of the linked list
14+
"""
15+
if not values:
16+
return None
17+
18+
# Create all nodes
19+
nodes = [ListNode(val) for val in values]
20+
21+
# Link nodes in sequence
22+
for i in range(len(nodes) - 1):
23+
nodes[i].next = nodes[i + 1]
24+
25+
# Create cycle if pos is valid
26+
if pos >= 0 and pos < len(nodes):
27+
nodes[-1].next = nodes[pos]
28+
29+
return nodes[0]
30+
31+
def test_first_pattern(self):
32+
# Input: head = [3,2,0,-4], pos = 1
33+
# Output: true
34+
solution = Solution()
35+
head = self.create_linked_list_with_cycle([3, 2, 0, -4], 1)
36+
output = solution.hasCycle(head)
37+
target = True
38+
self.assertEqual(output, target)
39+
40+
def test_second_pattern(self):
41+
# Input: head = [1,2], pos = 0
42+
# Output: true
43+
solution = Solution()
44+
head = self.create_linked_list_with_cycle([1, 2], 0)
45+
output = solution.hasCycle(head)
46+
target = True
47+
self.assertEqual(output, target)
48+
49+
def test_third_pattern(self):
50+
# Input: head = [1], pos = -1
51+
# Output: false
52+
solution = Solution()
53+
head = self.create_linked_list_with_cycle([1], -1)
54+
output = solution.hasCycle(head)
55+
target = False
56+
self.assertEqual(output, target)

0 commit comments

Comments
 (0)