Skip to content

Commit a7cca54

Browse files
committed
search: add search_rotated_sorted_array with tests
1 parent ed7a42e commit a7cca54

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/searching/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ mod ternary_search;
1414
mod ternary_search_min_max;
1515
mod ternary_search_min_max_recursive;
1616
mod ternary_search_recursive;
17+
mod search_rotated_sorted_array;
1718

1819
pub use self::binary_search::binary_search;
1920
pub use self::binary_search_recursive::binary_search_rec;
@@ -33,3 +34,4 @@ pub use self::ternary_search_min_max::ternary_search_min;
3334
pub use self::ternary_search_min_max_recursive::ternary_search_max_rec;
3435
pub use self::ternary_search_min_max_recursive::ternary_search_min_rec;
3536
pub use self::ternary_search_recursive::ternary_search_rec;
37+
pub use self::search_rotated_sorted_array::search_rotated_sorted_array;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//! Search for a target in a rotated sorted array.
2+
//!
3+
//! This implementation returns the index of `target` if present, or `None`.
4+
//! It assumes the input slice contains distinct elements and was originally
5+
//! sorted in ascending order before rotation.
6+
7+
/// Searches for `target` in a rotated sorted slice and returns its index.
8+
///
9+
/// Time complexity: O(log n)
10+
pub fn search_rotated_sorted_array<T: Ord>(arr: &[T], target: &T) -> Option<usize> {
11+
if arr.is_empty() {
12+
return None;
13+
}
14+
15+
let mut left: isize = 0;
16+
let mut right: isize = (arr.len() - 1) as isize;
17+
18+
while left <= right {
19+
let mid = left + (right - left) / 2;
20+
let mid_usize = mid as usize;
21+
22+
if &arr[mid_usize] == target {
23+
return Some(mid_usize);
24+
}
25+
26+
// Determine which half is normally ordered
27+
if arr[left as usize] <= arr[mid_usize] {
28+
// Left half is sorted
29+
if &arr[left as usize] <= target && target < &arr[mid_usize] {
30+
right = mid - 1;
31+
} else {
32+
left = mid + 1;
33+
}
34+
} else {
35+
// Right half is sorted
36+
if &arr[mid_usize] < target && target <= &arr[right as usize] {
37+
left = mid + 1;
38+
} else {
39+
right = mid - 1;
40+
}
41+
}
42+
}
43+
44+
None
45+
}
46+
47+
#[cfg(test)]
48+
mod tests {
49+
use super::*;
50+
51+
#[test]
52+
fn search_in_rotated_sorted_array_found_examples() {
53+
let arr = vec![4, 5, 6, 7, 0, 1, 2];
54+
assert_eq!(search_rotated_sorted_array(&arr, &0), Some(4));
55+
assert_eq!(search_rotated_sorted_array(&arr, &4), Some(0));
56+
assert_eq!(search_rotated_sorted_array(&arr, &2), Some(6));
57+
}
58+
59+
#[test]
60+
fn search_in_rotated_sorted_array_not_found() {
61+
let arr = vec![4, 5, 6, 7, 0, 1, 2];
62+
assert_eq!(search_rotated_sorted_array(&arr, &3), None);
63+
}
64+
65+
#[test]
66+
fn empty_and_single() {
67+
let empty: Vec<i32> = vec![];
68+
assert_eq!(search_rotated_sorted_array(&empty, &1), None);
69+
70+
let single = vec![1];
71+
assert_eq!(search_rotated_sorted_array(&single, &1), Some(0));
72+
assert_eq!(search_rotated_sorted_array(&single, &2), None);
73+
}
74+
}

0 commit comments

Comments
 (0)