Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,8 @@
* [Test Plates Between Candles](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/plates_between_candles/test_plates_between_candles.py)
* Rotated Sorted Array
* [Test Search Rotated Sorted Array](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/rotated_sorted_array/test_search_rotated_sorted_array.py)
* Search 2D Matrix
* [Test Search 2D Matrix](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/search_2d_matrix/test_search_2d_matrix.py)
* Search Range
* [Test Search Range](https://github.com/BrianLusina/PythonSnips/blob/master/algorithms/search/binary_search/search_range/test_search_range.py)
* Single Non Duplicate
Expand Down
14 changes: 14 additions & 0 deletions algorithms/search/binary_search/search_2d_matrix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Search a 2D Matrix

Given a two dimensional integer array matrix with m rows and n columns, determine whether the integer target exists in
matrix. Return true if target is present, otherwise return false.

The array matrix is sorted such that each row is in nondecreasing order, and the first element of each row is greater
than the last element of the previous row.

## Constraints

- m == matrix.length
- n == matrix[i].length
- 1 <= m,n <= 100
- -10^4 <= matrix[i][j], target <= 10^4
Comment thread
BrianLusina marked this conversation as resolved.
69 changes: 69 additions & 0 deletions algorithms/search/binary_search/search_2d_matrix/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from typing import List


def search_matrix(matrix: List[List[int]], target: int) -> bool:
"""
Search a 2D matrix for a target value. If the target value is found, return True, otherwise return False.
Args:
matrix (List[List[int]]): 2D matrix to search in.
target (int): Target value to search for.
Returns:
bool: True if the target value is found in the matrix, False otherwise.
"""
if not matrix:
return False
if not matrix[0]:
return False

n_rows = len(matrix)
n_cols = len(matrix[0])

left, right = 0, n_rows * n_cols - 1
while left <= right:
mid = (left + right) // 2
row, col = mid // n_cols, mid % n_cols
if matrix[row][col] == target:
return True
elif matrix[row][col] < target:
left = mid + 1
else:
right = mid - 1
return False


def search_matrix_2(matrix: List[List[int]], target: int) -> bool:
"""
Search a 2D matrix for a target value. If the target value is found, return True, otherwise return False.
Args:
matrix (List[List[int]]): 2D matrix to search in.
target (int): Target value to search for.
Returns:
bool: True if the target value is found in the matrix, False otherwise.
"""
# Get dimensions of the matrix
num_rows, num_cols = len(matrix), len(matrix[0])

# Initialize binary search boundaries
# Treat the 2D matrix as a flattened 1D array
left, right = 0, num_rows * num_cols - 1
first_true_index = -1

# Binary search using the template: find first index where element >= target
while left <= right:
mid = (left + right) // 2

# Convert 1D index to 2D coordinates
row, col = divmod(mid, num_cols)

# Feasible condition: matrix[row][col] >= target
if matrix[row][col] >= target:
first_true_index = mid
right = mid - 1
else:
left = mid + 1

# Check if first_true_index points to the target
if first_true_index == -1:
return False
row, col = divmod(first_true_index, num_cols)
return matrix[row][col] == target
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import unittest
from typing import List
from parameterized import parameterized
from utils.test_utils import custom_test_name_func
from algorithms.search.binary_search.search_2d_matrix import (
search_matrix,
search_matrix_2,
)

SEARCH_2D_MATRIX_TEST_CASES = [
([[-8, -3, 1, 4], [7, 9, 13, 18], [21, 26, 31, 40]], 13, True),
([[-6]], 5, False),
([[-5, -2, 0], [3, 6, 10]], -9, False),
([[-10, -4, 2, 9, 15, 22]], 9, True),
([[-9], [-1], [5], [12], [20]], 6, False),
([[0]], 0, True),
([[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]], 3, True),
([[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]], 13, False),
]


class Search2DMatrixTestCase(unittest.TestCase):
@parameterized.expand(SEARCH_2D_MATRIX_TEST_CASES, name_func=custom_test_name_func)
def test_search_2d_matrix(
self, matrix: List[List[int]], target: int, expected: bool
):
actual = search_matrix(matrix, target)
self.assertEqual(expected, actual)

@parameterized.expand(SEARCH_2D_MATRIX_TEST_CASES, name_func=custom_test_name_func)
def test_search_2d_matrix_2(
self, matrix: List[List[int]], target: int, expected: bool
):
actual = search_matrix_2(matrix, target)
self.assertEqual(expected, actual)


if __name__ == "__main__":
unittest.main()
24 changes: 20 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading