Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
- Integers in each row are sorted from left to right.
- The first integer of each row is greater than the last integer of the previous row.
For example,
Consider the following matrix:
[ [1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 50] ]
Given target = 3
, return true
.
在一个二维的矩阵里查找某个元素是否存在~矩阵每一行都是有序的,并且下一行的第一个元素值比这行的最后一个元素值大~
记得貌似在剑指offer这本书里看到过一个类似的题,那道题里矩阵的每行每列也都是是有序的,但不保证下一行的第一个元素值比这行的最后一个元素值大,思路是采取右上角的一个数字,与target比较,如果相同的话,返回True;如果右上角的值小于target,则target不可能在这一行里,可以把这一行剔除掉(维护两个index);如果值大于target,则说明target不可能在这一列,把这一列剔除掉;这样每一步都可以缩小查找的范围~算法时间复杂度应该是O(m+n)~
代码如下(写的时候对这题还有点印象,然后一次就AC了)
class Solution:
# @param matrix, a list of lists of integers
# @param target, an integer
# @return a boolean
def searchMatrix(self, matrix, target):
if matrix is None or len(matrix) == 0 or len(matrix[0]) == 0: return False
row, col = len(matrix), len(matrix[0])
i, j = 0, col - 1
while i < row and j >= 0:
if matrix[i][j] == target:
return True
elif matrix[i][j] > target:
j = j - 1
else:
i = i + 1
return False
看了一下其他解法~在时间复杂度上还可以提升~可以进行两次二分查找,把时间复杂度改进为O(logm + logn)~先按行查找,定位到某行,然后再按列查找~代码如下(写的时候要注意一下第一个二分搜索, 容易出错)
class Solution:
# @param matrix, a list of lists of integers
# @param target, an integer
# @return a boolean
def searchMatrix(self, matrix, target):
if matrix is None or len(matrix) == 0 or len(matrix[0]) == 0: return False
rowLen, colLen = len(matrix), len(matrix[0])
l, r = 0, rowLen - 1
while l <= r:
mid = l + (r - l) / 2
if matrix[mid][0] == target: return True
elif matrix[mid][0] > target: r = mid - 1
else: l = mid + 1
row = r
if row < 0: return False
l, r = 0, colLen - 1
while l <= r:
mid = l + (r - l) / 2
if matrix[row][mid] == target: return True
elif matrix[row][mid] > target: r = mid - 1
else: l = mid + 1
return False
还有另外一种解法,就是把2维矩阵当成一个1维的数组,然后在一维数组里用二分搜索查找~简化成的一维数组长度为rowLen * colLen; 中间值在二维矩阵里对应的是matrix[mid / colLen][mid % colLen]~ 时间复杂度是O(log(m*n)) = O(logm + logn),与进行两次二分搜索的复杂度一样~ 但有人认为这种解法还有一些缺陷:首先,m*n可能会溢出;其次,引进了大量的复杂运算:/ 和 % ~ (不过python 自带大数整数运算,整数不会溢出,只要内存足够)
class Solution:
# @param matrix, a list of lists of integers
# @param target, an integer
# @return a boolean
def searchMatrix(self, matrix, target):
if matrix is None or len(matrix) == 0 or len(matrix[0]) == 0: return False
rowLen, colLen = len(matrix), len(matrix[0])
l, r = 0, rowLen * colLen - 1
while l <= r:
mid = l + (r - l) / 2
midVal = matrix[mid / colLen][mid % colLen]
if midVal == target: return True
elif midVal < target:
l = mid + 1
else:
r = mid - 1
return False