Given an M x N integer matrix matrix and an integer target, return true if target exists in the matrix, otherwise return false.
The matrix has two special properties:
Each row is sorted from left to right.
The first element of every row is greater than the last element of the previous row.
Example 1
Input: matrix = [[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]], target = 3
Output: true
Explanation: 3 is present in the first row, so the answer is true.
Example 2
Input: matrix = [[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]], target = 13
Output: false
Explanation: 13 is not present in any row of 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 that does not exist.
Traverse each row one by one because the target can be anywhere in the matrix.
Inside every row, traverse each column and compare the current cell with the target.
If the current value matches the target, return
trueimmediately because the answer has already been found.If the full matrix is checked and no match appears, return
falsebecause the target is not present.
Dry Run
Search in a 2d Matrix Brute Dry Run
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 startsint 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, N is 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 is this: the matrix is not just row-wise sorted. It is sorted in a stronger way. The last value of one row is smaller than the first value of the next row. Because of that, if the matrix is read row by row, it becomes one fully sorted sequence.
For example:
[[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]]
behaves like:
[1, 3, 5, 7, 10, 11, 16, 20, 23, 30, 34, 60]
Now the problem starts looking exactly like normal binary search. The only tricky part is that the matrix is still stored in 2D form. So instead of actually creating a new 1D array, a virtual 1D index is used.
If there are cols columns:
row = mid / colstells which row the middle position belongs to.col = mid % colstells which column inside that row should be checked.
This is why binary search works here without flattening the matrix in memory.
Algorithm
First, check whether the matrix is empty. This is needed so the number of columns can be read safely and Store
rowsandcolsbecause these values are used again and again to control the search and map indices correctly.Treat the full matrix like a virtual sorted array of size
rows * cols. This is done because binary search needs one sorted search space and Keep two pointers,low = 0andhigh = rows * cols - 1, so the search starts with the entire virtual array.Find the middle index using
mid = low + (high - low) / 2. This gives the current candidate position without risking overflow in languages like C++ and Java.Convert that 1D index into a real matrix position using
row = mid / colsandcol = mid % cols. This step is needed because the data is stored as a matrix, not as an actual 1D array.Compare
matrix[row][col]with the target. If both are equal, returntruebecause the target has been found.If the middle value is smaller than the target, move
lowtomid + 1because every value on the left side is also too small.Otherwise, move
hightomid - 1because the middle value and everything on the right side are too large.If the loop finishes, return
falsebecause no position matched the target.
Dry Run
Search in a 2D Matrix Optimal Dry Run
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 index mapping. int rows = (int)matrix.size(); int cols = (int)matrix[0].size(); // Search boundaries of the virtual 1D sorted array. int low = 0; int high = rows * cols - 1; while (low <= high) { // Pick the middle position of the current search space. int mid = low + (high - low) / 2; // Convert the virtual 1D index into the real matrix position. int row = mid / cols; // This gives the column inside the chosen row. int col = mid % cols; // Read the actual value stored at the mapped position. int current = matrix[row][col]; // Return immediately because the target is found here. if (current == target) { return true; } // Move right because the target must be after this smaller value. if (current < target) { low = mid + 1; } else { // Move left because this value and everything after it are too large. high = mid - 1; } } return false; }};// Driver code startsint 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(log2(M x N)), M is the number of rows and N is the number of columns, because our search space is M x N so binary search gives us log2(M xN)
Space Complexity: O(1), because constant space is used.
Interview follow-up Questions
Because every row is sorted, and each new row starts with a value greater than the last value of the previous row. So the full row-by-row order is sorted.
Be the first to add a comment.