Created
May 24, 2013 19:32
-
-
Save Nicksil/5645958 to your computer and use it in GitHub Desktop.
Python - Matrix Find
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# File: MatrixFind.py | |
# Author: Keith Schwarz ([email protected]) | |
# | |
# An algorithm for finding a specific value in a specially-formatted matrix of | |
# values. | |
# | |
# The algorithm takes as input a matrix of values where each row and each | |
# column are in sorted order, along with a value to locate in that array, then | |
# returns whether that element exists in the matrix. For example, given the | |
# matrix | |
# | |
# 1 2 2 2 3 4 | |
# 1 2 3 3 4 5 | |
# 3 4 4 4 4 6 | |
# 4 5 6 7 8 9 | |
# | |
# along with the number 7, the algorithm would output YES, but if given the | |
# number 0 the algorithm would output NO. | |
# | |
# One approach for solving this problem would be a simple exhaustive search of | |
# the matrix to find the value. If the matrix dimensions are m x n, this | |
# algorithm will take time O(mn) in the worst-case, which is indeed linear in | |
# the size of the matrix but takes no advantage of the sorted structure we are | |
# guaranteed to have in the matrix. Our goal will be to find a much faster | |
# algorithm for solving the same problem. | |
# | |
# One approach that might be useful for solving the problem is to try to keep | |
# deleting rows or columns out of the array in a way that reduces the problem | |
# size without ever deleting the value (should it exist). For example, suppose | |
# that we iteratively start deleting rows and columns from the matrix that we | |
# know do not contain the value. We can repeat this until either we've reduced | |
# the matrix down to nothingness, in which case we know that the element is not | |
# present, or until we find the value. If the matrix is m x n, then this would | |
# require only O(m + n) steps, which is much faster than the O(mn) approach | |
# outlined above. | |
# | |
# In order to realize this as a concrete algorithm, we'll need to find a way to | |
# determine which rows or columns to drop. One particularly elegant way to do | |
# this is to look at the very last element of the first row of the matrix. | |
# Consider how it might relate to the value we're looking for. If it's equal | |
# to the value in question, we're done and can just hand back that we've found | |
# the entry we want. If it's greater than the value in question, since each | |
# column is in sorted order, we know that no element of the last column could | |
# possibly be equal to the number we want to search for, and so we can discard | |
# the last column of the matrix. Finally, if it's less than the value in | |
# question, then we know that since each row is in sorted order, none of the | |
# values in the first row can equal the element in question, since they're no | |
# bigger than the last element of that row, which is in turn smaller than the | |
# element in question. This gives a very straightforward algorithm for finding | |
# the element - we keep looking at the last element of the first row, then | |
# decide whether to discard the last row or the last column. As mentioned | |
# above, this will run in O(m + n) time. (Thanks to Prof. David Gries of | |
# Cornell University for this solution). | |
# Function: matrixFind(matrix, value) | |
# Usage: result = matrixFind(myMatrix, 137) | |
# ----------------------------------------------------------------------------- | |
# Searches the given matrix, which must have its rows and columns in sorted | |
# order, for the given value, returning whether or not that value was found. | |
def matrixFind(matrix, value): | |
# Get the matrix dimensions. If the matrix is empty, return that we could | |
# not find the value in question. | |
m = len(matrix) | |
if m == 0: | |
return False | |
n = len(matrix[0]) | |
if n == 0: | |
return False | |
# Maintain the index (i, j) of the last element of the first row. We will | |
# be using this index to keep track of the next location to look. | |
i = 0 | |
j = n - 1 | |
# Keep comparing the last element of the first row of the matrix to the | |
# element in question, paring down a row or column as appropriate. If we | |
# ever walk off the matrix, we know that the element must not exist. | |
while i < m and j >= 0: | |
# If we found the value, great! We're done. | |
if matrix[i][j] == value: | |
return True | |
# Otherwise, if the value here is smaller than the value we're looking | |
# for, we can exclude this row from consideration. | |
elif matrix[i][j] < value: | |
i = i + 1 | |
# Otherwise, the value here is greater, so we can exclude this column | |
# from consideration. | |
else: | |
j = j - 1 | |
return False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment