Skip to content

Commit 1fb9023

Browse files
committed
ref: let saddleback search check if the input is sorted
1 parent 78bd242 commit 1fb9023

File tree

1 file changed

+67
-8
lines changed

1 file changed

+67
-8
lines changed

src/searching/saddleback_search.rs

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,85 @@ use std::cmp::Ordering;
33
/// Custom error type to represent errors related to matrix validation.
44
#[derive(Debug, PartialEq, Eq)]
55
pub enum MatrixError {
6-
NonRectangularMatrix,
6+
NonRectangularInput,
7+
NotSorted,
78
}
89

9-
/// Performs Saddleback search on a sorted 2D matrix.
10+
/// Checks if the given matrix (vector of vectors) is sorted row-wise and column-wise.
11+
///
12+
/// A matrix is considered sorted if
13+
///
14+
/// * Each row is sorted in non-decreasing order.
15+
/// * Each column is sorted in non-decreasing order.
16+
///
17+
/// # Arguments
18+
///
19+
/// * `matrix` - A vector of vectors representing the matrix to check.
20+
///
21+
/// # Returns
22+
///
23+
/// Returns `true` if the matrix is sorted both row-wise and column-wise. Otherwise, returns `false`.
24+
fn is_sorted(matrix: &[Vec<isize>]) -> bool {
25+
if matrix.is_empty() || matrix.iter().all(|row| row.is_empty()) {
26+
return true;
27+
}
28+
29+
let rows = matrix.len();
30+
let cols = matrix[0].len();
31+
32+
// Check if rows are sorted.
33+
for row in matrix {
34+
if row.windows(2).any(|w| w[0] > w[1]) {
35+
return false;
36+
}
37+
}
38+
39+
// Check if columns are sorted.
40+
for col in 0..cols {
41+
for row in 1..rows {
42+
if matrix[row - 1][col] > matrix[row][col] {
43+
return false;
44+
}
45+
}
46+
}
47+
48+
true
49+
}
50+
51+
/// Performs Saddleback search on a sorted matrix represented as a vector of vectors.
1052
///
1153
/// The Saddleback search algorithm finds the position of a target element in a matrix where
1254
/// each row and each column is sorted in ascending order. The search starts from the top-right
1355
/// corner of the matrix and moves left or down based on comparisons with the target element.
1456
///
57+
/// Optionally, the matrix can be validated for being sorted before the search starts.
58+
///
1559
/// # Arguments
1660
///
17-
/// * `matrix` - A 2D vector representing the sorted matrix.
61+
/// * `matrix` - A vector of vectors representing the sorted matrix.
1862
/// * `element` - The target element to search for.
63+
/// * `check_sorted` - If true, verifies that the matrix is sorted before performing the search.
1964
///
2065
/// # Returns
2166
///
2267
/// Returns `Ok(Some((row, column)))` where both indices are 0-based if the element is found.
2368
/// Returns `Ok(None)` if the element is not found.
24-
/// Returns `Err(MatrixError)` if the matrix is not rectangular.
69+
/// Returns `Err(MatrixError)` if the matrix is not rectangular or not sorted.
2570
pub fn saddleback_search(
2671
matrix: &[Vec<isize>],
2772
element: isize,
73+
check_sorted: bool,
2874
) -> Result<Option<(usize, usize)>, MatrixError> {
2975
if matrix.is_empty() || matrix.iter().all(|row| row.is_empty()) {
3076
return Ok(None);
3177
}
3278

3379
if matrix.iter().any(|row| row.len() != matrix[0].len()) {
34-
return Err(MatrixError::NonRectangularMatrix);
80+
return Err(MatrixError::NonRectangularInput);
81+
}
82+
83+
if check_sorted && !is_sorted(matrix) {
84+
return Err(MatrixError::NotSorted);
3585
}
3686

3787
let mut left_index = 0;
@@ -66,7 +116,7 @@ mod tests {
66116
#[test]
67117
fn $name() {
68118
let (matrix, element, expected) = $tc;
69-
assert_eq!(saddleback_search(&matrix, element), expected);
119+
assert_eq!(saddleback_search(&matrix, element, true), expected);
70120
}
71121
)*
72122
};
@@ -171,7 +221,7 @@ mod tests {
171221
vec![3, 30, 300],
172222
],
173223
20,
174-
Err::<Option<(usize, usize)>, MatrixError>(MatrixError::NonRectangularMatrix),
224+
Err::<Option<(usize, usize)>, MatrixError>(MatrixError::NonRectangularInput),
175225
),
176226
test_empty_row: (
177227
vec![
@@ -180,7 +230,7 @@ mod tests {
180230
vec![4, 5, 6],
181231
],
182232
3,
183-
Err::<Option<(usize, usize)>, MatrixError>(MatrixError::NonRectangularMatrix),
233+
Err::<Option<(usize, usize)>, MatrixError>(MatrixError::NonRectangularInput),
184234
),
185235
test_full_empty_rows: (
186236
vec![
@@ -192,5 +242,14 @@ mod tests {
192242
1,
193243
Ok(None::<(usize, usize)>),
194244
),
245+
test_unsorted_matrix_with_check: (
246+
vec![
247+
vec![1, 10, 100],
248+
vec![20, 200, 2],
249+
vec![3, 30, 300],
250+
],
251+
200,
252+
Err::<Option<(usize, usize)>, MatrixError>(MatrixError::NotSorted),
253+
),
195254
}
196255
}

0 commit comments

Comments
 (0)