use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug)]
pub struct ListNode<T> {
pub val: T,
pub next: Option<Rc<RefCell<ListNode<T>>>>,
}
impl<T> ListNode<T> {
pub fn new(val: T) -> Self {
ListNode { val, next: None }
}
}
pub fn has_cycle<T>(head: &Option<Rc<RefCell<ListNode<T>>>>) -> bool {
let mut slow = head.clone();
let mut fast = head.clone();
while let Some(f) = fast {
let next_fast = f.borrow().next.clone();
if let Some(f2) = next_fast {
fast = f2.borrow().next.clone();
} else {
return false;
}
if let Some(s) = slow.clone() {
slow = s.borrow().next.clone();
}
if let (Some(sf), Some(ff)) = (slow.clone(), fast.clone()) {
if Rc::ptr_eq(&sf, &ff) {
return true;
}
} else {
return false;
}
}
false
}
pub fn find_cycle_start<T>(
head: &Option<Rc<RefCell<ListNode<T>>>>,
) -> Option<Rc<RefCell<ListNode<T>>>> {
if head.is_none() {
return None;
}
let mut slow = head.clone();
let mut fast = head.clone();
let mut intersection: Option<Rc<RefCell<ListNode<T>>>> = None;
while let Some(f) = fast {
let next_fast = f.borrow().next.clone();
if let Some(f2) = next_fast {
fast = f2.borrow().next.clone();
} else {
return None; }
if let Some(s) = slow.clone() {
slow = s.borrow().next.clone();
}
if let (Some(sf), Some(ff)) = (slow.clone(), fast.clone()) {
if Rc::ptr_eq(&sf, &ff) {
intersection = Some(sf);
break;
}
} else {
return None;
}
}
intersection.as_ref()?;
let mut ptr1 = head.clone();
let mut ptr2 = intersection;
while let (Some(p1), Some(p2)) = (ptr1, ptr2) {
if Rc::ptr_eq(&p1, &p2) {
return Some(p1);
}
ptr1 = p1.borrow().next.clone();
ptr2 = p2.borrow().next.clone();
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_empty_list() {
assert_eq!(has_cycle::<i32>(&None), false);
assert!(find_cycle_start::<i32>(&None).is_none());
}
#[test]
fn test_single_node_no_cycle() {
let n1 = Rc::new(RefCell::new(ListNode::new(42)));
let head = Some(n1.clone());
assert_eq!(has_cycle(&head), false);
assert!(find_cycle_start(&head).is_none());
}
#[test]
fn test_two_nodes_no_cycle() {
let n1 = Rc::new(RefCell::new(ListNode::new(1)));
let n2 = Rc::new(RefCell::new(ListNode::new(2)));
n1.borrow_mut().next = Some(n2.clone());
let head = Some(n1.clone());
assert_eq!(has_cycle(&head), false);
assert!(find_cycle_start(&head).is_none());
}
#[test]
fn test_small_cycle() {
let n1 = Rc::new(RefCell::new(ListNode::new(1)));
let n2 = Rc::new(RefCell::new(ListNode::new(2)));
let n3 = Rc::new(RefCell::new(ListNode::new(3)));
n1.borrow_mut().next = Some(n2.clone());
n2.borrow_mut().next = Some(n3.clone());
n3.borrow_mut().next = Some(n2.clone());
let head = Some(n1.clone());
assert_eq!(has_cycle(&head), true);
let start = find_cycle_start(&head).unwrap();
assert!(Rc::ptr_eq(&start, &n2));
}
#[test]
fn test_longer_cycle() {
let n1 = Rc::new(RefCell::new(ListNode::new(1)));
let n2 = Rc::new(RefCell::new(ListNode::new(2)));
let n3 = Rc::new(RefCell::new(ListNode::new(3)));
let n4 = Rc::new(RefCell::new(ListNode::new(4)));
let n5 = Rc::new(RefCell::new(ListNode::new(5)));
n1.borrow_mut().next = Some(n2.clone());
n2.borrow_mut().next = Some(n3.clone());
n3.borrow_mut().next = Some(n4.clone());
n4.borrow_mut().next = Some(n5.clone());
n5.borrow_mut().next = Some(n3.clone());
let head = Some(n1.clone());
assert_eq!(has_cycle(&head), true);
let start = find_cycle_start(&head).unwrap();
assert!(Rc::ptr_eq(&start, &n3));
}
#[test]
fn test_no_cycle_long_list() {
let n1 = Rc::new(RefCell::new(ListNode::new(1)));
let n2 = Rc::new(RefCell::new(ListNode::new(2)));
let n3 = Rc::new(RefCell::new(ListNode::new(3)));
let n4 = Rc::new(RefCell::new(ListNode::new(4)));
let n5 = Rc::new(RefCell::new(ListNode::new(5)));
n1.borrow_mut().next = Some(n2.clone());
n2.borrow_mut().next = Some(n3.clone());
n3.borrow_mut().next = Some(n4.clone());
n4.borrow_mut().next = Some(n5.clone());
let head = Some(n1.clone());
assert_eq!(has_cycle(&head), false);
assert!(find_cycle_start(&head).is_none());
}
}