Skip to content

Commit fce048f

Browse files
authored
Refactor partially sorted matrix search algorithms
Refactor matrix value search implementation and improve comments.
1 parent 53380da commit fce048f

File tree

1 file changed

+77
-143
lines changed

1 file changed

+77
-143
lines changed
Lines changed: 77 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,182 +1,116 @@
11
/*
22
* Task: Determine whether a target value exists in a row/column-sorted matrix.
33
*
4-
* Matrix Value Search
4+
* MATRIX VALUE SEARCH
55
*
6-
* Given a matrix where each row and each column is sorted in ascending order,
7-
* determine if a given target value exists within the matrix.
6+
* The matrix has the following properties:
7+
* - Each row is sorted left-to-right
8+
* - Each column is sorted top-to-bottom
89
*
9-
* Constraints and Expectations:
10-
* - Each row is sorted left-to-right.
11-
* - Each column is sorted top-to-bottom.
12-
* - The task is to implement two solutions:
13-
* 1. A Simple (Divide and Conquer) Approach: Uses recursion to narrow down
14-
* the search space.
15-
* 2. An Optimal (Staircase) Approach: Iteratively searches from the top-right
16-
* corner.
17-
* - An alternative brute-force solution is also provided for educational
18-
* comparison.
19-
*
20-
* ASCII Illustration of the Matrix:
21-
* +----+----+----+----+
22-
* | 1 | 2 | 8 | 9 |
23-
* +----+----+----+----+
24-
* | 2 | 4 | 9 | 12 |
25-
* +----+----+----+----+
26-
* | 4 | 7 | 10 | 13 |
27-
* +----+----+----+----+
28-
* | 6 | 8 | 11 | 15 |
29-
* +----+----+----+----+
30-
*
31-
* Example:
32-
* Input: Matrix as shown above, Target = 7
33-
* Output: true
34-
* Explanation: The value 7 is located at row 3, column 2 (0-indexed) of the
35-
* matrix.
10+
* Example matrix:
11+
* { 1, 2, 8, 9 }
12+
* { 2, 4, 9, 12 }
13+
* { 4, 7, 10, 13 }
14+
* { 6, 8, 11, 15 }
3615
*/
3716

38-
#include <algorithm>
3917
#include <iostream>
4018
#include <string>
4119
#include <vector>
4220

43-
// Simple (Divide and Conquer) Solution
44-
// Recursive approach: divides the matrix into submatrices based on the middle
45-
// element. Average complexity may be better than brute-force, though worst-case
46-
// may involve overlapping searches.
47-
bool simpleSolutionHelper(const std::vector<std::vector<int>> &matrix,
48-
int value, int row1, int col1, int row2, int col2) {
49-
if (row1 > row2 || col1 > col2)
50-
return false;
51-
52-
// If target is outside the current submatrix's range, skip search.
53-
if (value < matrix[row1][col1] || value > matrix[row2][col2])
54-
return false;
55-
56-
// Directly check boundaries.
57-
if (value == matrix[row1][col1] || value == matrix[row2][col2])
58-
return true;
59-
60-
int midRow = (row1 + row2) / 2;
61-
int midCol = (col1 + col2) / 2;
62-
63-
if (matrix[midRow][midCol] == value)
64-
return true;
65-
66-
if (value < matrix[midRow][midCol]) {
67-
// Exclude the bottom-right quadrant.
68-
return simpleSolutionHelper(matrix, value, row1, col1, midRow,
69-
midCol - 1) ||
70-
simpleSolutionHelper(matrix, value, row1, midCol, midRow - 1,
71-
col2) ||
72-
simpleSolutionHelper(matrix, value, midRow + 1, col1, row2,
73-
midCol - 1);
21+
// ----------------------- 1) Simple (Brute-force) Solution --------------------
22+
// Check every element in the matrix until the target is found.
23+
//
24+
// Time Complexity:
25+
// - O(n * m), where n = rows, m = columns
26+
//
27+
// Space Complexity:
28+
// - O(1) extra space
29+
//
30+
bool searchMatrixSimple(const std::vector<std::vector<int>>& matrix, int target) {
31+
for (const auto& row : matrix) {
32+
for (int value : row) {
33+
if (value == target) return true;
34+
}
7435
}
75-
76-
// value > mid: exclude the top-left quadrant.
77-
return simpleSolutionHelper(matrix, value, midRow, midCol + 1, row2, col2) ||
78-
simpleSolutionHelper(matrix, value, midRow + 1, col1, row2, midCol) ||
79-
simpleSolutionHelper(matrix, value, row1, midCol + 1, midRow - 1,
80-
col2);
81-
}
82-
83-
bool simpleSolution(const std::vector<std::vector<int>> &matrix, int value) {
84-
if (matrix.empty() || matrix.front().empty())
85-
return false;
86-
return simpleSolutionHelper(matrix, value, 0, 0,
87-
static_cast<int>(matrix.size()) - 1,
88-
static_cast<int>(matrix[0].size()) - 1);
36+
return false;
8937
}
9038

91-
// Optimal (Staircase) Solution
92-
// Iterative approach starting from the top-right corner, reducing the search
93-
// space at each step. Complexity: O(n + m), where n is the number of rows and m
94-
// is the number of columns.
95-
bool optimalSolution(const std::vector<std::vector<int>> &matrix, int value) {
96-
if (matrix.empty() || matrix.front().empty())
97-
return false;
98-
99-
int rows = matrix.size(), cols = matrix[0].size();
100-
int row = 0, col = cols - 1;
101-
102-
while (row < rows && col >= 0) {
103-
if (matrix[row][col] == value)
39+
// ----------------------- 2) Optimal (Staircase) Solution ---------------------
40+
//
41+
// - Start at the top-right corner.
42+
// - If current value > target → move left.
43+
// - If current value < target → move down.
44+
// - Eliminate one row or column at each step.
45+
//
46+
// Time Complexity:
47+
// - O(n + m)
48+
// Each step removes a row or a column from consideration.
49+
//
50+
// Space Complexity:
51+
// - O(1) extra space
52+
//
53+
bool searchMatrixOptimal(const std::vector<std::vector<int>>& matrix,
54+
int target) {
55+
if (matrix.empty() || matrix[0].empty()) return false;
56+
57+
int rows = matrix.size();
58+
int cols = matrix[0].size();
59+
60+
int r = 0;
61+
int c = cols - 1;
62+
63+
while (r < rows && c >= 0) {
64+
if (matrix[r][c] == target)
10465
return true;
105-
else if (matrix[row][col] > value)
106-
--col;
66+
else if (matrix[r][c] > target)
67+
--c; // move left
10768
else
108-
++row;
69+
++r; // move down
10970
}
110-
11171
return false;
11272
}
11373

114-
// (Optional) Alternative Solution
115-
// Brute-force search for educational purposes. Complexity: O(n * m)
116-
bool alternativeSolution(const std::vector<std::vector<int>> &matrix,
117-
int value) {
118-
for (const auto &row : matrix)
119-
for (const auto &elem : row)
120-
if (elem == value)
121-
return true;
122-
return false;
123-
}
124-
125-
namespace {
74+
// ------------------------------ Tests (2 examples) ---------------------------
12675
struct TestRunner {
12776
int total = 0;
12877
int failed = 0;
12978

130-
void expectEqual(bool got, bool expected, const std::string &label) {
79+
void expect(bool got, bool expected, const std::string& label) {
13180
++total;
13281
if (got == expected) {
13382
std::cout << "[PASS] " << label << "\n";
134-
return;
83+
} else {
84+
++failed;
85+
std::cout << "[FAIL] " << label << " expected=" << std::boolalpha
86+
<< expected << " got=" << got << "\n";
13587
}
136-
++failed;
137-
std::cout << "[FAIL] " << label << " expected=" << std::boolalpha
138-
<< expected << " got=" << got << "\n";
13988
}
14089

14190
void summary() const {
142-
std::cout << "Tests: " << total - failed << " passed, " << failed
143-
<< " failed, " << total << " total\n";
91+
std::cout << "Tests: " << (total - failed) << " passed, "
92+
<< failed << " failed, " << total << " total\n";
14493
}
14594
};
146-
} // namespace
14795

148-
// Test cases for correctness
149-
void test() {
150-
std::vector<std::vector<int>> matrix{
151-
{1, 2, 8, 9}, {2, 4, 9, 12}, {4, 7, 10, 13}, {6, 8, 11, 15}};
152-
TestRunner runner;
96+
int main() {
97+
std::vector<std::vector<int>> matrix = {
98+
{1, 2, 8, 9},
99+
{2, 4, 9, 12},
100+
{4, 7, 10, 13},
101+
{6, 8, 11, 15}
102+
};
153103

154-
// Test for a value that exists in the matrix.
155-
runner.expectEqual(simpleSolution(matrix, 7), true, "simple contains 7");
156-
runner.expectEqual(optimalSolution(matrix, 7), true, "optimal contains 7");
157-
runner.expectEqual(alternativeSolution(matrix, 7), true,
158-
"alternative contains 7");
104+
TestRunner t;
159105

160-
// Test for a value that does not exist.
161-
runner.expectEqual(simpleSolution(matrix, 5), false, "simple missing 5");
162-
runner.expectEqual(optimalSolution(matrix, 5), false, "optimal missing 5");
163-
runner.expectEqual(alternativeSolution(matrix, 5), false,
164-
"alternative missing 5");
106+
// Example 1: target exists
107+
t.expect(searchMatrixSimple(matrix, 7), true, "simple: contains 7");
108+
t.expect(searchMatrixOptimal(matrix, 7), true, "optimal: contains 7");
165109

166-
// Test boundaries.
167-
runner.expectEqual(simpleSolution(matrix, 1), true, "simple contains 1");
168-
runner.expectEqual(optimalSolution(matrix, 1), true, "optimal contains 1");
169-
runner.expectEqual(alternativeSolution(matrix, 1), true,
170-
"alternative contains 1");
110+
// Example 2: target does not exist
111+
t.expect(searchMatrixSimple(matrix, 5), false, "simple: missing 5");
112+
t.expect(searchMatrixOptimal(matrix, 5), false, "optimal: missing 5");
171113

172-
runner.expectEqual(simpleSolution(matrix, 15), true, "simple contains 15");
173-
runner.expectEqual(optimalSolution(matrix, 15), true, "optimal contains 15");
174-
runner.expectEqual(alternativeSolution(matrix, 15), true,
175-
"alternative contains 15");
176-
runner.summary();
177-
}
178-
179-
int main() {
180-
test();
181-
return 0;
114+
t.summary();
115+
return (t.failed == 0) ? 0 : 1;
182116
}

0 commit comments

Comments
 (0)