Search in a Row and Column-Wise Sorted Matrix

96.7k
0

Given an M x N integer matrix matrix and an integer target, return true if target exists in the matrix, otherwise return false.

In this matrix:

  • Each row is sorted from left to right.

  • Each column is sorted from top to bottom.

Example 1

Input: matrix = [[1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30]], target = 5

Output: true

Explanation: 5 is present in the matrix, so the answer is true.

Example 2

Input: matrix = [[1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30]], target = 20

Output: false

Explanation: 20 does not appear anywhere in the matrix.

Brute Force Approach

The simplest thought is to just check every value one by one.

If any cell matches the target, the search can stop immediately.

This approach is useful as a starting point because it matches exactly what the problem is asking, even though it does not use the matrix properties in a smart way.

Algorithm

  • First, check whether the matrix is empty. This is needed so the code does not try to access a row or column that does not exist.

  • Traverse every row because the target can be in any part of the matrix.

  • Inside each row, traverse every column and compare the current value with the target.

  • If the current value matches the target, return true immediately because the answer has been found.

  • If the full matrix is checked and no match appears, return false because the target is not present.

Dry Run

Brute

Brute

Solution

#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/*
Returns true if the target
exists anywhere in the matrix.
*/
bool searchMatrix(vector<vector<int>>& matrix, int target) {
// Stop early if the matrix has no usable cells.
if (matrix.empty() || matrix[0].empty()) {
return false;
}
for (int i = 0; i < (int)matrix.size(); i++) {
for (int j = 0; j < (int)matrix[i].size(); j++) {
// Return immediately because the target is found here.
if (matrix[i][j] == target) {
return true;
}
}
}
return false;
}
};
// Driver code starts
int main() {
vector<vector<int>> matrix = {
{1, 3, 5, 7},
{10, 11, 16, 20},
{23, 30, 34, 60}
};
int target = 3;
Solution obj;
cout << (obj.searchMatrix(matrix, target) ? "true" : "false") << endl;
return 0;
}

Complexity Analysis

Time Complexity: O(M x N), M is the number of rows and N is the number of columns, because in the worst case every cell of the matrix may need to be checked.

Space Complexity: O(1), because constant space is used.

Optimal Approach

The unlocking observation comes from choosing the right starting corner. The top-right element is a very special position.

  • Everything on its left is smaller.

  • Everything below it is larger.

That means one comparison is enough to decide one whole direction. If the current value is larger than the target, moving down makes things even larger, so that cannot help. The only useful move is left.

If the current value is smaller than the target, moving left makes things even smaller, so that cannot help either. The only useful move is down.

This is the full reason the method works. Each step removes one row or one column from consideration, so the search keeps shrinking in a very controlled way.

This pattern often feels like walking down a staircase, which is why this method is commonly called staircase search.

Algorithm

  • First, check whether the matrix is empty. This is needed so the search does not try to read an invalid corner position.

  • Start from the top-right cell using row = 0 and col = cols - 1. This corner is chosen because it gives opposite directions: left becomes smaller and down becomes larger.

  • Compare the current value with the target. If both values are equal, return true immediately because the target has been found.

  • If the current value is greater than the target, move left by decreasing col. This is done because the full current column below this cell is even larger, so that column cannot contain the target at this position or below.

  • If the current value is smaller than the target, move down by increasing row. This is done because the full current row to the left is even smaller, so staying in that row cannot help anymore.

  • Keep repeating this process while row stays inside the matrix and col stays inside the matrix.

  • If the search goes out of bounds, return false because every useful row or column has already been ruled out.

Key Points

  • This problem is not globally sorted like Search in a 2D Matrix, so flattening into a virtual 1D array does not work here. Check the article on Search in a 2D Matrix

  • Starting from the bottom-left corner also works for the same reason, just with opposite moves.

Dry Run

Optimal

Optimal

Solution

#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/*
Returns true if the target
exists anywhere in the matrix.
*/
bool searchMatrix(vector<vector<int>>& matrix, int target) {
// Stop early if the matrix has no usable cells.
if (matrix.empty() || matrix[0].empty()) {
return false;
}
// These store the matrix dimensions for boundary checks.
int rows = (int)matrix.size();
int cols = (int)matrix[0].size();
// Start from the top-right corner to remove one row or column each step.
int row = 0;
int col = cols - 1;
while (row < rows && col >= 0) {
// Read the current corner value of the remaining search area.
int current = matrix[row][col];
// Return immediately because the target is found here.
if (current == target) {
return true;
}
// Move left because everything below this value is even larger.
if (current > target) {
col--;
} else {
// Move down because everything left of this value is even smaller.
row++;
}
}
return false;
}
};
// Driver code starts
int main() {
vector<vector<int>> matrix = {
{1, 4, 7, 11, 15},
{2, 5, 8, 12, 19},
{3, 6, 9, 16, 22},
{10, 13, 14, 17, 24},
{18, 21, 23, 26, 30}
};
int target = 5;
Solution obj;
cout << (obj.searchMatrix(matrix, target) ? "true" : "false") << endl;
return 0;
}

Complexity Analysis

Time Complexity: O(M + N),M is the number of rows and N is the number of columns,because in each step one row or one column is removed from the search.

Space Complexity: O(1), because constant space is used.

Interview follow-up Questions

Starting from the top-left corner does not work for this strategy. If the target is larger than the number at the top-left, you have two choices to find a larger number: you can move right or you can move down. Because both directions lead to larger numbers, you cannot definitively eliminate a row or a column, which breaks the logic.

MathsArraysBinary SearchTwo PointerSorting

Read Similar Blogs

Comments0