在问 · 算法题解

74. 搜索二维矩阵

中等二分查找一次二分查找(展平为一维)力扣原题 ↗

题目描述

输入一个 m x n 的整数矩阵 matrix 和整数 target。矩阵满足两点:每一行从左到右单调不减;每一行开头的数都比上一行末尾的数大。

换句话说,把各行首尾相接,就得到一个有序序列。

如果 target 出现在矩阵中,返回 true,否则返回 false。算法的时间复杂度要求为 O(log(m * n))。

示例 1
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

解释:3 在第 0 行。

示例 2
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false

解释:13 介于 11 和 16 之间,矩阵里没有它。

数据范围

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 100
  • -10^4 <= matrix[i][j], target <= 10^4

解题思路:一次二分查找(展平为一维)

将矩阵映射为一维数组二分。

为什么正确

候选区间始终包含答案。

复杂度分析

时间 O(log(mn)),额外空间 O(1)。

易错点

注意边界条件并在回溯或弹出后恢复状态。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
 def searchMatrix(self,a,t):
  if not a or not a[0]:return False
  m,n=len(a),len(a[0]);l,h=0,m*n-1
  while l<=h:
   x=(l+h)//2;v=a[x//n][x%n]
   if v==t:return True
   if v<t:l=x+1
   else:h=x-1
  return False

载入编辑器,自己跑一遍 →

其他解法

展平二分利用了“整个矩阵按行拼接后有序”,O(log(mn)) 最快;右上角排除只要求行、列各自有序,更通用,但需要 O(m+n)。

解法 2:右上角出发排除(Z 字形查找) 时间 O(m+n),空间 O(1)

从右上角开始。当前元素是所在行的最大值、所在列的最小值:如果它大于 target,整列都大于 target,向左移一列;如果小于 target,整行都小于 target,向下移一行;相等就找到了。每一步都会排除一行或一列,最多走 m+n 步。

只依赖行内递增、列内递增,所以也能解第 240 题这种更弱的条件。本题条件更强,O(m+n) 比二分的 O(log(mn)) 慢。

class Solution:
    def searchMatrix(self, matrix, target):
        m, n = len(matrix), len(matrix[0])
        i, j = 0, n - 1
        while i < m and j >= 0:
            v = matrix[i][j]
            if v == target:
                return True
            if v > target:
                j -= 1
            else:
                i += 1
        return False

二分查找 专题的其他题目

查看 二分查找 全部题目 →