@@ -3,35 +3,85 @@ use std::cmp::Ordering;
33/// Custom error type to represent errors related to matrix validation.
44#[ derive( Debug , PartialEq , Eq ) ]
55pub 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 .
2570pub 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