在问 · 算法题解

240. 搜索二维矩阵 II

中等数组与矩阵右上角 Z 字形查找力扣原题 ↗

题目描述

输入一个 m x n 的整数矩阵 matrix 和一个整数 target。

矩阵有两个性质:每一行从左往右递增,每一列从上往下递增。

判断 target 是否出现在矩阵中,出现返回 true,否则返回 false。要求算法尽量高效。

示例 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

解释:5 位于第 2 行第 2 列。

示例 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

解释:矩阵中没有 20。

数据范围

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= n, m <= 300
  • -10^9 <= matrix[i][j] <= 10^9
  • 每一行从左往右升序。
  • 每一列从上往下升序。
  • -10^9 <= target <= 10^9

解题思路:右上角 Z 字形查找

从右上角开始:当前值大于 target 则左移,当前值小于 target 则下移。每步排除一整行或一整列。

为什么正确

指针所在位置的左下矩形仍包含所有可能的 target。

复杂度分析

时间 O(m+n),空间 O(1)。

易错点

从左上角出发无法同时根据大小排除一整行或一整列。

参考代码

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

class Solution:
    def searchMatrix(self, matrix,target):
        if not matrix: return False
        r,c=0,len(matrix[0])-1
        while r<len(matrix) and c>=0:
            if matrix[r][c]==target: return True
            if matrix[r][c]>target: c-=1
            else: r+=1
        return False

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

其他解法

逐行二分只用到行有序,O(m log n);Z 字形查找同时利用行和列的有序性,每步排除一行或一列,O(m + n)。

解法 2:逐行二分 时间 O(m log n),空间 O(1)

每一行都是升序的,对每一行单独做二分查找,任何一行找到 target 就返回 true。可以用行首剪枝:行首已大于 target 时,下面的行都不可能含 target。

只用到了“行有序”,写法简单。没有利用列有序来排除整行整列,当 m 和 n 接近时比 Z 字形查找慢。

import bisect

class Solution:
    def searchMatrix(self, matrix, target):
        for row in matrix:
            if not row or row[0] > target:
                break
            i = bisect.bisect_left(row, target)
            if i < len(row) and row[i] == target:
                return True
        return False

数组与矩阵 专题的其他题目

查看 数组与矩阵 全部题目 →