From a7cca548951c546d2d75d67216ae7e6341a3d455 Mon Sep 17 00:00:00 2001 From: bivekk51 Date: Sun, 5 Oct 2025 11:26:41 +0545 Subject: [PATCH 1/3] search: add search_rotated_sorted_array with tests --- src/searching/mod.rs | 2 + src/searching/search_rotated_sorted_array.rs | 74 ++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 src/searching/search_rotated_sorted_array.rs diff --git a/src/searching/mod.rs b/src/searching/mod.rs index 94f65988195..3bab0d20b47 100644 --- a/src/searching/mod.rs +++ b/src/searching/mod.rs @@ -14,6 +14,7 @@ mod ternary_search; mod ternary_search_min_max; mod ternary_search_min_max_recursive; mod ternary_search_recursive; +mod search_rotated_sorted_array; pub use self::binary_search::binary_search; pub use self::binary_search_recursive::binary_search_rec; @@ -33,3 +34,4 @@ pub use self::ternary_search_min_max::ternary_search_min; pub use self::ternary_search_min_max_recursive::ternary_search_max_rec; pub use self::ternary_search_min_max_recursive::ternary_search_min_rec; pub use self::ternary_search_recursive::ternary_search_rec; +pub use self::search_rotated_sorted_array::search_rotated_sorted_array; diff --git a/src/searching/search_rotated_sorted_array.rs b/src/searching/search_rotated_sorted_array.rs new file mode 100644 index 00000000000..33683185ba7 --- /dev/null +++ b/src/searching/search_rotated_sorted_array.rs @@ -0,0 +1,74 @@ +//! Search for a target in a rotated sorted array. +//! +//! This implementation returns the index of `target` if present, or `None`. +//! It assumes the input slice contains distinct elements and was originally +//! sorted in ascending order before rotation. + +/// Searches for `target` in a rotated sorted slice and returns its index. +/// +/// Time complexity: O(log n) +pub fn search_rotated_sorted_array(arr: &[T], target: &T) -> Option { + if arr.is_empty() { + return None; + } + + let mut left: isize = 0; + let mut right: isize = (arr.len() - 1) as isize; + + while left <= right { + let mid = left + (right - left) / 2; + let mid_usize = mid as usize; + + if &arr[mid_usize] == target { + return Some(mid_usize); + } + + // Determine which half is normally ordered + if arr[left as usize] <= arr[mid_usize] { + // Left half is sorted + if &arr[left as usize] <= target && target < &arr[mid_usize] { + right = mid - 1; + } else { + left = mid + 1; + } + } else { + // Right half is sorted + if &arr[mid_usize] < target && target <= &arr[right as usize] { + left = mid + 1; + } else { + right = mid - 1; + } + } + } + + None +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn search_in_rotated_sorted_array_found_examples() { + let arr = vec![4, 5, 6, 7, 0, 1, 2]; + assert_eq!(search_rotated_sorted_array(&arr, &0), Some(4)); + assert_eq!(search_rotated_sorted_array(&arr, &4), Some(0)); + assert_eq!(search_rotated_sorted_array(&arr, &2), Some(6)); + } + + #[test] + fn search_in_rotated_sorted_array_not_found() { + let arr = vec![4, 5, 6, 7, 0, 1, 2]; + assert_eq!(search_rotated_sorted_array(&arr, &3), None); + } + + #[test] + fn empty_and_single() { + let empty: Vec = vec![]; + assert_eq!(search_rotated_sorted_array(&empty, &1), None); + + let single = vec![1]; + assert_eq!(search_rotated_sorted_array(&single, &1), Some(0)); + assert_eq!(search_rotated_sorted_array(&single, &2), None); + } +} From 0e965482e8170183aa725dc6284ad32b49a69d2c Mon Sep 17 00:00:00 2001 From: bivekk51 Date: Sun, 5 Oct 2025 11:44:07 +0545 Subject: [PATCH 2/3] test: add edge-case tests for search_rotated_sorted_array --- src/searching/mod.rs | 4 +-- src/searching/search_rotated_sorted_array.rs | 34 ++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/searching/mod.rs b/src/searching/mod.rs index 3bab0d20b47..98f57dcd632 100644 --- a/src/searching/mod.rs +++ b/src/searching/mod.rs @@ -10,11 +10,11 @@ mod linear_search; mod moore_voting; mod quick_select; mod saddleback_search; +mod search_rotated_sorted_array; mod ternary_search; mod ternary_search_min_max; mod ternary_search_min_max_recursive; mod ternary_search_recursive; -mod search_rotated_sorted_array; pub use self::binary_search::binary_search; pub use self::binary_search_recursive::binary_search_rec; @@ -28,10 +28,10 @@ pub use self::linear_search::linear_search; pub use self::moore_voting::moore_voting; pub use self::quick_select::quick_select; pub use self::saddleback_search::saddleback_search; +pub use self::search_rotated_sorted_array::search_rotated_sorted_array; pub use self::ternary_search::ternary_search; pub use self::ternary_search_min_max::ternary_search_max; pub use self::ternary_search_min_max::ternary_search_min; pub use self::ternary_search_min_max_recursive::ternary_search_max_rec; pub use self::ternary_search_min_max_recursive::ternary_search_min_rec; pub use self::ternary_search_recursive::ternary_search_rec; -pub use self::search_rotated_sorted_array::search_rotated_sorted_array; diff --git a/src/searching/search_rotated_sorted_array.rs b/src/searching/search_rotated_sorted_array.rs index 33683185ba7..f1c8b9386aa 100644 --- a/src/searching/search_rotated_sorted_array.rs +++ b/src/searching/search_rotated_sorted_array.rs @@ -71,4 +71,38 @@ mod tests { assert_eq!(search_rotated_sorted_array(&single, &1), Some(0)); assert_eq!(search_rotated_sorted_array(&single, &2), None); } + + #[test] + fn non_rotated_array() { + // already sorted ascending + let arr = vec![0, 1, 2, 3, 4, 5]; + assert_eq!(search_rotated_sorted_array(&arr, &0), Some(0)); + assert_eq!(search_rotated_sorted_array(&arr, &5), Some(5)); + assert_eq!(search_rotated_sorted_array(&arr, &3), Some(3)); + assert_eq!(search_rotated_sorted_array(&arr, &6), None); + } + + #[test] + fn small_rotations_and_edges() { + // rotation by 1 + let arr1 = vec![5, 0, 1, 2, 3, 4]; + assert_eq!(search_rotated_sorted_array(&arr1, &5), Some(0)); + assert_eq!(search_rotated_sorted_array(&arr1, &4), Some(5)); + + // rotation by len-1 (same as rotation by -1) + let arr2 = vec![1, 2, 3, 4, 5, 0]; + assert_eq!(search_rotated_sorted_array(&arr2, &0), Some(5)); + assert_eq!(search_rotated_sorted_array(&arr2, &1), Some(0)); + } + + #[test] + fn two_elements_varieties() { + let a = vec![1, 2]; + assert_eq!(search_rotated_sorted_array(&a, &1), Some(0)); + assert_eq!(search_rotated_sorted_array(&a, &2), Some(1)); + + let b = vec![2, 1]; + assert_eq!(search_rotated_sorted_array(&b, &1), Some(1)); + assert_eq!(search_rotated_sorted_array(&b, &2), Some(0)); + } } From 23b8eb859e68764d1e376fb52f2fe4e0b5db236e Mon Sep 17 00:00:00 2001 From: bivekk51 Date: Sun, 5 Oct 2025 12:00:41 +0545 Subject: [PATCH 3/3] chore(ci): trigger CI re-run (no-op)