-
-
Notifications
You must be signed in to change notification settings - Fork 2.4k
/
Copy pathfloyds_algorithm.rs
95 lines (79 loc) · 2.71 KB
/
floyds_algorithm.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// floyds_algorithm.rs
// https://github.com/rust-lang/rust/blob/master/library/alloc/src/collections/linked_list.rs#L113
// use std::collections::linked_list::LinkedList;
// https://www.reddit.com/r/rust/comments/t7wquc/is_it_possible_to_solve_leetcode_problem141/
use crate::data_structures::linked_list::LinkedList; // Import the LinkedList from linked_list.rs
pub fn detect_cycle<T>(linked_list: &LinkedList<T>) -> Option<usize> {
let mut current = linked_list.head;
let mut checkpoint = linked_list.head;
let mut steps_until_reset = 1;
let mut times_reset = 0;
while let Some(node) = current {
steps_until_reset -= 1;
if steps_until_reset == 0 {
checkpoint = current;
times_reset += 1;
steps_until_reset = 1 << times_reset; // 2^times_reset
}
unsafe {
let node_ptr = node.as_ptr();
let next = (*node_ptr).next;
current = next;
}
if current == checkpoint {
return Some(linked_list.length as usize);
}
}
None
}
pub fn has_cycle<T>(linked_list: &LinkedList<T>) -> bool {
let mut slow = linked_list.head;
let mut fast = linked_list.head;
while let (Some(slow_node), Some(fast_node)) = (slow, fast) {
unsafe {
slow = slow_node.as_ref().next;
fast = fast_node.as_ref().next;
if let Some(fast_next) = fast {
// fast = (*fast_next.as_ptr()).next;
fast = fast_next.as_ref().next;
} else {
return false; // If fast reaches the end, there's no cycle
}
if slow == fast {
return true; // Cycle detected
}
}
}
// println!("{}", flag);
false // No cycle detected
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detect_cycle_no_cycle() {
let mut linked_list = LinkedList::new();
linked_list.insert_at_tail(1);
linked_list.insert_at_tail(2);
linked_list.insert_at_tail(3);
assert!(!has_cycle(&linked_list));
assert_eq!(detect_cycle(&linked_list), None);
}
#[test]
fn test_detect_cycle_with_cycle() {
let mut linked_list = LinkedList::new();
linked_list.insert_at_tail(1);
linked_list.insert_at_tail(2);
linked_list.insert_at_tail(3);
// Create a cycle for testing
unsafe {
if let Some(mut tail) = linked_list.tail {
if let Some(head) = linked_list.head {
tail.as_mut().next = Some(head);
}
}
}
assert!(has_cycle(&linked_list));
assert_eq!(detect_cycle(&linked_list), Some(3));
}
}