本文为Python算法题集之一的代码示例
编写一个高效的算法来搜索 *m* x *n*
矩阵 matrix
中的一个目标值 target
。该矩阵具有以下特性:
示例 1:
输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
输出:true
示例 2:
输入:matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
输出:false
提示:
m == matrix.length
n == matrix[i].length
1 <= n, m <= 300
-109 <= matrix[i][j] <= 109
-109 <= target <= 109
通常优化:减少循环层次
通常优化:增加分支,减少计算集
通常优化:采用内置算法来提升计算速度
分析题目特点,分析最优解
因矩阵行列均已排序,因此可以在每个数组中判断搜索范围
既可以判断左边界,也可以判断右边界
对角线的元素有个特点,左上的元素都小于等于它,右下的元素都大于等于它,可以用它控制检索范围
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块标准双层循环,意外性能还行,看来大家大部分代码都是这么写的,非常简洁
import CheckFuncPerf as cfp
def searchMatrix_base(matrix, target) :
iheight, iwidth = len(matrix), len(matrix[0])
for iIdx in range(iheight):
for jIdx in range(iwidth):
if matrix[iIdx][jIdx] == target:
return True
return False
import random,copy
matrix = []
for iIdx in range(1000):
matrix.append([random.randint(0, 1000000) for x in range(1000)])
for iIdx in range(100):
matrix[iIdx].sort()
sortedmatrix = [sorted(column) for column in zip(*matrix)]
iTarget = sortedmatrix[888][879]
matrixCopy = copy.deepcopy(sortedmatrix)
result = cfp.getTimeMemoryStr(searchMatrix_base, matrixCopy, iTarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
# 运行结果
函数 searchMatrix_base 的运行时间为 16.96 ms;内存使用量为 4.00 KB 执行结果 = True
行检测最大值是否过小,有少量优化
import CheckFuncPerf as cfp
def searchMatrix_ext1(matrix, target):
iheight, iwidth = len(matrix), len(matrix[0])
for iIdx in range(iheight):
if matrix[iIdx][iwidth-1] >= target:
for jIdx in range(iwidth):
if matrix[iIdx][jIdx] == target:
return True
return False
import random,copy
matrix = []
for iIdx in range(1000):
matrix.append([random.randint(0, 1000000) for x in range(1000)])
for iIdx in range(100):
matrix[iIdx].sort()
sortedmatrix = [sorted(column) for column in zip(*matrix)]
iTarget = sortedmatrix[888][879]
matrixCopy = copy.deepcopy(sortedmatrix)
result = cfp.getTimeMemoryStr(searchMatrix_ext1, matrixCopy, iTarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
# 运行结果
函数 searchMatrix_ext1 的运行时间为 16.95 ms;内存使用量为 0.00 KB 执行结果 = True
在对角线判断可能出现区域,计算量最小,但是代码最复杂,调试时间最长,相应维护起来也会更困难;如无绝对必要,不要这么写
import CheckFuncPerf as cfp
def searchMatrix_ext2(matrix, target):
iheight, iwidth = len(matrix), len(matrix[0])
if matrix[iheight-1][iwidth-1] < target:
return False
if matrix[0][0] > target:
return False
istart, istop, iminedge = -1, -1, min(iheight, iwidth)
for iIdx in range(iminedge):
if matrix[iIdx][iIdx] == target:
return True
elif matrix[iIdx][iIdx] < target:
istart = iIdx
else:
istop = iIdx
break
if iheight>iwidth:
for iIdx in range(iwidth, iheight):
if matrix[iIdx][iwidth-1] >= target:
for jIdx in range(iwidth):
if matrix[iIdx][jIdx] == target:
return True
elif iwidth>iheight:
for iIdx in range(iheight):
if matrix[iIdx][iwidth-1] >= target:
for jIdx in range(iheight, iwidth):
if matrix[iIdx][jIdx] == target:
return True
if istop == -1:
return False
for iIdx in range(0, istart+1):
for jidx in range(istart, iwidth):
if matrix[iIdx][jidx] == target:
return True
for iIdx in range(istart, iheight):
for jidx in range(0, istop+1):
if matrix[iIdx][jidx] == target:
return True
for iIdx in range(0, iwidth):
if matrix[istart][iIdx] == target:
return True
for iIdx in range(0, iheight):
if matrix[iIdx][istart] == target:
return True
for iIdx in range(0, iwidth):
if matrix[istop][iIdx] == target:
return True
for iIdx in range(0, iheight):
if matrix[iIdx][istop] == target:
return True
return False
import random,copy
matrix = []
for iIdx in range(1000):
matrix.append([random.randint(0, 1000000) for x in range(1000)])
for iIdx in range(100):
matrix[iIdx].sort()
sortedmatrix = [sorted(column) for column in zip(*matrix)]
iTarget = sortedmatrix[888][879]
matrixCopy = copy.deepcopy(sortedmatrix)
result = cfp.getTimeMemoryStr(searchMatrix_ext2, matrixCopy, iTarget)
print(result['msg'], '执行结果 = {}'.format(result['result']))
# 运行结果
函数 searchMatrix_ext2 的运行时间为 3.99 ms;内存使用量为 0.00 KB 执行结果 = True
根据本地日志分析,最优算法为第3种searchMatrix_ext2
import random,copy
matrix = []
for iIdx in range(1000):
matrix.append([random.randint(0, 1000000) for x in range(1000)])
for iIdx in range(100):
matrix[iIdx].sort()
sortedmatrix = [sorted(column) for column in zip(*matrix)]
iTarget = sortedmatrix[888][879]
matrixCopy = copy.deepcopy(sortedmatrix)
# 6种算法本地速度实测比较
函数 searchMatrix_base 的运行时间为 16.96 ms;内存使用量为 4.00 KB 执行结果 = True
函数 searchMatrix_ext1 的运行时间为 16.95 ms;内存使用量为 0.00 KB 执行结果 = True
函数 searchMatrix_ext2 的运行时间为 3.99 ms;内存使用量为 0.00 KB 执行结果 = True
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~