
Problem Statement
In this problem, you are provided with a matrix that adheres to two specific properties: each row within the matrix is sorted in non-decreasing order, and the first element of each subsequent row is always greater than the last element of the previous row. Given such a structured matrix, you are tasked with determining if a specified integer (referred to as target) exists within this matrix. The challenge is to implement this search functionality with a time complexity of O(log(m * n)), where m is the number of rows and n is the number of columns in the matrix. This implies the need for an algorithm that is more efficient than a straightforward linear search, leveraging the ordered nature of the matrix to achieve logarithmic time complexity.
Examples
Example 1
Input:
matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
Output:
true
Example 2
Input:
matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
Output:
false
Constraints
m == matrix.lengthn == matrix[i].length1 <= m, n <= 100-104 <= matrix[i][j], target <= 104
Approach and Intuition
The structured nature of the matrix allows us to employ a search technique that takes advantage of both the sorted rows and the ordered inter-row transition. This can intuitively lead us to a binary search strategy, not just over rows or columns individually, but over the matrix as a whole. Here's the guiding logic:
- Treat the matrix as if it were a single sorted array. Given the properties of the matrix, we can map a 2D index pair
(i, j)to a single index in a hypothetical 1D array version of this matrix. - Start with binary search:
- Calculate the middle index of this conceptual 1D array.
- Convert this 1D index back to a 2D index pair
(i, j). Determineiby dividing the index by the number of columns. Findjby taking the index modulo the number of columns. - Compare the element at matrix[i][j] with the target:
- If they match, return
true. - If the matrix element is larger than the target, move the search to the left half.
- Otherwise, move to the right half.
- If they match, return
- If we exhaust the search space and haven't found the target, return
false.
This approach ensures that each step of the search cuts the search space in half, resulting in a logarithmic time complexity relative to the total number of elements in the matrix, hence achieving the desired O(log(m * n)) performance.
Solutions
- C++
- Java
- C
- JavaScript
- Python
class Solution {
public:
bool findInMatrix(vector<vector<int>>& grid, int value) {
int rows = grid.size();
if (rows == 0)
return false;
int cols = grid[0].size();
int start = 0, end = rows * cols - 1;
int midIndex, midValue;
while (start <= end) {
midIndex = (start + end) / 2;
midValue = grid[midIndex / cols][midIndex % cols];
if (value == midValue)
return true;
else {
if (value < midValue)
end = midIndex - 1;
else
start = midIndex + 1;
}
}
return false;
}
};
This summary explains how the findInMatrix function written in C++ efficiently searches for a value within a 2D matrix. The algorithm treats the matrix as if it were a 1D array, enabling the use of binary search for optimal performance.
Follow these steps to understand how the function operates:
- Determine the number of rows in the matrix. If there are no rows, the matrix is empty and return
false. - Calculate the number of columns based on the first row.
- Set initial search boundaries with
startset to 0 andendset to the last index in the matrix (rows * cols - 1). - Utilize a loop to execute until
startis less than or equal toend. - Calculate
midIndexas the average ofstartandend. - Derive
midValueusingmidIndexto access the corresponding element in the matrix, accounting for row and column placement. - If the
valuematchesmidValue, returntrue. - If the
valueis less thanmidValue, adjustendtomidIndex - 1to search the lower half. - If the
valueis greater thanmidValue, adjuststarttomidIndex + 1to search the upper half. - If the loop concludes without finding the value, return
false.
This algorithm ensures a time-efficient search with a complexity of O(log(n)), where n is the total number of elements in the matrix. This approach significantly improves performance over a linear search especially for large matrices.
class Solution {
public boolean findInMatrix(int[][] grid, int value) {
int rows = grid.length;
if (rows == 0) return false;
int cols = grid[0].length;
int start = 0, end = rows * cols - 1;
int mid, middleElement;
while (start <= end) {
mid = (start + end) / 2;
middleElement = grid[mid / cols][mid % cols];
if (value == middleElement) return true;
else {
if (value < middleElement) end = mid - 1;
else start = mid + 1;
}
}
return false;
}
}
The provided solution outlines an efficient method for searching a value in a 2D matrix using Java. The matrix is interpreted as a 1D sorted array to apply binary search, which increases the search efficiency compared to a linear scan.
In this process:
Initialize
rowsas the total number of rows in the matrix and directly return false if the matrix is empty, i.e.,rowsis zero.Determine the number of columns containing
cols.Set two pointers,
startandend, to cover the entire virtual 1D array representation of the matrix.startis at 0, andendis atrows * cols - 1.Use a
whileloop to execute untilstartexceedsend. In each iteration, computemidto split the dataset andmiddleElementto fetch the value of the midpoint using matrix indexing.If
valuematchesmiddleElement, return true, indicating the value is found.If
valueis less thanmiddleElement, adjustendto narrow the search to the left half by setting it tomid - 1.Otherwise, adjust
startto narrow the search to the right half by setting it tomid + 1.If no match is found by the end of the loop, return false.
Adopt this binary search approach in a 2D matrix to significantly reduce the time complexity from linear to logarithmic, which is particularly advantageous when dealing with large datasets.
bool findInMatrix(int** grid, int rowCount, int* colSize, int searchValue) {
if (rowCount == 0) return false;
int cols = colSize[0];
int start = 0, end = rowCount * cols - 1;
int midIndex, midValue;
while (start <= end) {
midIndex = (start + end) / 2;
midValue = grid[midIndex / cols][midIndex % cols];
if (searchValue == midValue)
return true;
else {
if (searchValue < midValue)
end = midIndex - 1;
else
start = midIndex + 1;
}
}
return false;
}
Solve the "Search a 2D Matrix" problem effectively using this provided C function findInMatrix. This function is designed to search for a specific integer, termed searchValue, within a matrix represented as a pointer to a pointer of integers, grid. Here are the key functionalities encapsulated in the implementation:
Begin by handling the edge case where the matrix is empty. If
rowCountequals zero, the function immediately returns false, indicating the absence of any search value.Calculate the total number of columns in the matrix with
int cols = colSize[0];. This utilizes the first element of thecolSizearray for understanding matrix dimensions.Implement a binary search approach across the flattened matrix structure:
- Initialize two pointers,
startat 0 andendat the last index of the flattened matrix, calculated asrowCount * cols - 1. - Iterate while
startis less than or equal toend. Compute the middle index,midIndex, and its corresponding value,midValue, using matrix row and column calculations. - Compare
midValuewithsearchValue. If they match, return true indicating the searchValue is found. - Depending on whether
searchValueis less than or greater thanmidValue, adjust theendorstartpointers respectively to narrow down the search space.
- Initialize two pointers,
If the loop terminates without finding the
searchValue, return false to indicate its absence in the matrix.
This function effectively leverages the sorted nature of the matrix, employing a flattened version of the binary search, which leads to an efficient solution with time complexity O(log(m*n)), where m is the number of rows and n is the number of columns in the matrix.
var findInMatrix = function (mat, val) {
let rows = mat.length;
if (rows == 0) return false;
let cols = mat[0].length;
let start = 0,
end = rows * cols - 1;
let mid, element;
while (start <= end) {
mid = Math.floor((start + end) / 2);
element = mat[Math.floor(mid / cols)][mid % cols];
if (val == element) return true;
else {
if (val < element) end = mid - 1;
else start = mid + 1;
}
}
return false;
};
In this solution, you are introduced to a method findInMatrix, implemented in JavaScript, which searches for a value in a 2D matrix. This implementation employs a binary search technique to efficiently locate the target value within the matrix.
- The function accepts two parameters:
mat(the matrix), andval(the value to find). - First, determine the number of rows in the matrix. If there are no rows (
rows == 0), the function returnsfalse, indicating the value is not found. - Next, compute the number of columns in the matrix.
- Define starting (
start) and ending (end) points for the binary search. These are set based on the total number of elements in the matrix (rows * cols - 1). - Use a
whileloop to perform the binary search:- Compute the middle point (
mid) of the current search range. - Convert this index into a row and column index in the 2D matrix to access the corresponding element.
- If the target value (
val) matches the element at the calculated position in the matrix, returntrue. - Adjust the
startandendpointers depending on whether the target value is less or greater than the current element, narrowing the search range accordingly.
- Compute the middle point (
- If the search loop completes without finding the value, return
false.
This efficient searching method leverages the ordered structure of a flattened 2D array, offering a time complexity of O(log(m*n)), where m is the number of matrix rows and n is the number of matrix columns. This approach is significantly faster than a linear search, especially for larger matrices.
class Solution:
def findTarget(self, grid: List[List[int]], key: int) -> bool:
row_count = len(grid)
if row_count == 0:
return False
col_count = len(grid[0])
left, right = 0, row_count * col_count - 1
while left <= right:
mid = (left + right) // 2
current = grid[mid // col_count][mid % col_count]
if key == current:
return True
elif key < current:
right = mid - 1
else:
left = mid + 1
return False
This Python solution efficiently searches for a target value within a 2D matrix by viewing the matrix as a flattened sorted array. Follow the steps outlined below to understand the approach taken in this implementation:
- Calculate the total number of rows in the matrix using
len(grid). ReturnFalseif the matrix is empty. - Determine the number of columns in the matrix with
len(grid[0]). - Establish a range for binary search by setting
leftto 0 andrightto(row_count * col_count - 1), essentially treating the 2D matrix as a 1D array. - Initiate a loop that continues as long as
leftis less than or equal toright. - Calculate the midpoint
midas(left + right) // 2. - Convert the
midindex to the corresponding indices in the 2D matrix format, usingmid // col_countfor the row index andmid % col_countfor the column index. - Compare the target
keywith the value at the calculated row and column index:- If the target equals the current matrix value, return
True. - If the target is smaller, adjust the
rightindex tomid - 1. - If the target is larger, adjust the
leftindex tomid + 1.
- If the target equals the current matrix value, return
- If the loop exits without finding the target, return
False.
This method uses a binary search algorithm, ensuring the solution is efficient with a time complexity of O(log(m*n)), where m is the number of rows and n the number of columns. This is ideal for large datasets, as it minimizes the number of comparisons needed to find the target value.