Search in 2D Matrix in DSA Rust - Time & Space Complexity
We want to understand how long it takes to find a number in a 2D matrix.
How does the search time grow as the matrix gets bigger?
Analyze the time complexity of the following code snippet.
fn search_matrix(matrix: &Vec>, target: i32) -> bool {
for row in matrix {
for &num in row {
if num == target {
return true;
}
}
}
false
}
This code checks every number in the matrix until it finds the target or finishes all elements.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Checking each element in the matrix.
- How many times: Once for each element, until target is found or all checked.
As the matrix size grows, the number of checks grows with the total elements.
| Input Size (n x m) | Approx. Operations |
|---|---|
| 10 x 10 (100) | Up to 100 checks |
| 100 x 100 (10,000) | Up to 10,000 checks |
| 1000 x 1000 (1,000,000) | Up to 1,000,000 checks |
Pattern observation: The work grows proportionally to the total number of elements.
Time Complexity: O(n * m)
This means the time to search grows directly with the number of rows times columns.
[X] Wrong: "Since each row is sorted, searching one row is always fast, so total search is O(n)."
[OK] Correct: The code checks every element without using sorting to skip parts, so it still may check all elements.
Understanding this helps you explain how simple searches work and why using sorting or special methods can speed things up.
"What if the matrix rows and columns are sorted and we use a smarter search? How would the time complexity change?"
Practice
Solution
Step 1: Understand matrix sorting property
Each row is sorted and the first element of a row is greater than the last element of the previous row, so the entire matrix can be seen as a sorted list.Step 2: Apply binary search on the flattened matrix
We can treat the matrix as a single sorted list and use binary search to find the target efficiently.Final Answer:
Use binary search treating the matrix as a flattened sorted list -> Option AQuick Check:
Matrix sorted row-wise + binary search = Use binary search treating the matrix as a flattened sorted list [OK]
- Searching each row or column linearly wastes time
- Using hash map wastes extra space
- Ignoring the matrix's sorted property
Solution
Step 1: Avoid overflow in mid calculation
Using `(start + end) / 2` can overflow if start and end are large. The safer way is `start + (end - start) / 2`.Step 2: Check other options
let mid = (start - end) / 2; subtracts incorrectly, and D multiplies which is wrong for mid calculation.Final Answer:
let mid = start + (end - start) / 2; -> Option BQuick Check:
Safe mid calculation = let mid = start + (end - start) / 2; [OK]
- Using (start + end) / 2 causing overflow
- Using subtraction incorrectly for mid
- Multiplying indices instead of averaging
let matrix = vec![
vec![1, 3, 5, 7],
vec![10, 11, 16, 20],
vec![23, 30, 34, 60]
];
let target = 5;
let rows = matrix.len();
let cols = matrix[0].len();
let mut start = 0;
let mut end = rows * cols - 1;
let mut found = false;
while start <= end {
let mid = start + (end - start) / 2;
let r = mid / cols;
let c = mid % cols;
if matrix[r][c] == target {
found = true;
break;
} else if matrix[r][c] < target {
start = mid + 1;
} else {
end = mid - 1;
}
}
println!("{}", found);Solution
Step 1: Understand binary search on matrix
The code treats the matrix as a sorted list and uses binary search to find target 5.Step 2: Trace the search for target 5
5 is at matrix[0][2]. The binary search will find it and set found = true.Final Answer:
true -> Option DQuick Check:
Target 5 found = true [OK]
- Confusing row and column calculation
- Off-by-one errors in indices
- Not updating start or end correctly
let matrix = vec![
vec![1, 4, 7, 11],
vec![15, 20, 25, 30],
vec![35, 40, 45, 50]
];
let target = 20;
let rows = matrix.len();
let cols = matrix[0].len();
let mut start = 0;
let mut end = rows * cols;
while start <= end {
let mid = start + (end - start) / 2;
let r = mid / cols;
let c = mid % cols;
if matrix[r][c] == target {
println!("Found");
break;
} else if matrix[r][c] < target {
start = mid + 1;
} else {
end = mid - 1;
}
}Solution
Step 1: Check the range of end index
Matrix has rows * cols elements, so last index is rows * cols - 1, not rows * cols.Step 2: Fix end initialization
Set end = rows * cols - 1 to avoid out-of-bound access when mid equals rows * cols.Final Answer:
end should be rows * cols - 1 instead of rows * cols -> Option AQuick Check:
Index range off-by-one fixed = end should be rows * cols - 1 instead of rows * cols [OK]
- Setting end to rows * cols causing panic
- Swapping row and column calculations
- Incorrect loop condition
Solution
Step 1: Understand matrix property
Rows are sorted but no guarantee that first element of a row is greater than last of previous row, so flattened binary search won't work.Step 2: Use stair-step search from top-right
Starting at top-right, move left if current > target, move down if current < target, efficiently narrowing search.Final Answer:
Start from top-right corner and move left or down based on comparison -> Option CQuick Check:
Stair-step search fits matrix property = Start from top-right corner and move left or down based on comparison [OK]
- Assuming full matrix sorted for binary search
- Searching each row fully wasting time
- Using extra space unnecessarily
Ready to prove it?
Pass the test and this pattern moves unknown
