被列在「遞迴」的範圍內,所以用遞迴的方式解決。
該矩陣有一個特性,相同 y 或 相同 x 的欄列會照順序排。
得利用此特性來強化搜尋機制,不然硬方法全部遍歷(Traversal)一次就一定找得到。
按照前面的範例,選一個中間的點,該值小於目標值則捨棄右下方,該值大於目標值則捨棄左上方,然後遍歷同y或同x軸的元素。
如果只是單純的目標值小就往左上找,反之找右下,這樣是行不通的。
設想一下情境,找了一個元素,但不是目標值,接著就可以將矩陣切成四分,直接捨棄左上或右下的,剩下左下、右上及右下或左上的部分矩陣也需要尋找,於是最後會產生三個矩陣再繼續遞迴下去搜尋。
於是可以簡單地寫成:
class Solution: def searchMatrix(self, matrix, target): """ :type matrix: List[List[int]] :type target: int :rtype: bool """ def serach(yl, yu, xl, xu, target): if yl > yu or xl > xu: return False xm = (xu-xl)//2 + xl ym = (yu-yl)//2 + yl if matrix[ym][xm] == target: return True elif matrix[ym][xm] > target: # 往左下查詢 if serach(ym, yu, xl, xm-1, target): return True # 往左上查詢 if serach(yl, ym-1, xl, xm-1, target): return True # 往右上查詢 if serach(yl, ym-1, xm, xu, target): return True else: # 往右上查詢 if serach(yl, ym, xm+1, xu, target): return True # 往右下查詢 if serach(ym+1, yu, xm+1, xu, target): return True # 往左下查詢 if serach(ym+1, yu, xl, xm, target): return True return False if not matrix or not matrix[0]: return False return serach(0, len(matrix)-1, 0, len(matrix[0])-1, target)要注意不在左上與不在右下的差異,跟元素同x或同y座標的元素仍未被搜尋過,所以會被分給左下或是右上,因此兩者的右上、左下搜尋會有差異。
如果在搜尋的時候先把同x或同y座標的元素給找過,就可以再減少要搜尋的範圍。
class Solution: def searchMatrix(self, matrix, target): """ :type matrix: List[List[int]] :type target: int :rtype: bool """ def serach(yl, yu, xl, xu, target): if yl > yu or xl > xu: return False xm = (xu-xl)//2 + xl ym = (yu-yl)//2 + yl #print(yl, yu, xl, xu) if matrix[ym][xm] == target: return True elif matrix[ym][xm] > target: # 往上,決定右上查詢範圍 yu2 = ym - 1 for y in range(yl, yu2+1): if matrix[y][xm] == target: return True elif matrix[y][xm] > target: yu2 = y - 1 break if serach(yl, yu2, xm+1, xu, target): return True # 往左,決定左下查詢範圍 xu2 = xm - 1 for x in range(xl, xu2+1): if matrix[ym][x] == target: return True elif matrix[ym][x] > target: xu2 = x -1 break if serach(ym+1, yu, xl, xu2, target): return True # 往左上方查詢 if serach(yl, ym-1, xl, xm-1, target): return True else: # 往右,決定右上查詢範圍 xl2 = xm+1 for x in range(xl2, xu+1): if matrix[ym][x] == target: return True elif matrix[ym][x] > target: xl2 = x break if serach(yl, ym-1, xl2, xu, target): return True # 往下,決定左下查詢範圍 yl2 = ym+1 for y in range(yl2, yu+1): if matrix[y][xm] == target: return True elif matrix[y][xm] > target: yl2 = y break if serach(yl2, yu, xl, xm-1, target): return True # 往右下查詢 if serach(ym+1, yu, xm+1, xu, target): return True return False if not matrix or not matrix[0]: return False return serach(0, len(matrix)-1, 0, len(matrix[0])-1, target)雖然這樣的寫法未必找得快,但是如果碰上要找重複幾個時候,只要改一改就能通用了。
雖然一開始的直覺是直接一個個搜尋,但是這樣就不合使用遞迴的期待。
更快的寫法是從左下開始搜尋,不斷往右上方逼進,最大次數就是長寬相加。這妥善利用該矩陣的特性,只是沒有遞迴。