#LC74. 搜索二维矩阵

搜索二维矩阵

你好!作为教练,我很高兴能带你剖析这道经典的“矩阵搜索”问题。在 NOI 竞赛中,这属于基础算法应用范畴,考察的是你对单调性的敏锐观察力以及坐标映射的熟练度。


一、 题目描述 (NOI 竞赛格式)

题目名称:搜索二维矩阵 (Search a 2D Matrix) 文件输入matrix.in 文件输出matrix.out 时间限制:1.0s 内存限制:256MB

【问题描述】 给你一个 m×nm \times n 的整数矩阵 matrix ,它具有以下两个特点:

  1. 每行中的整数从左到右按非严格递增顺序排列。
  2. 每行的第一个整数大于前一行的最后一个整数。

给定一个目标值 target ,如果 target 在矩阵中,输出 true;否则,输出 false

【输入格式】 第一行包含两个整数 mmnn,表示矩阵的行数和列数。 接下来 mm 行,每行包含 nn 个整数,表示矩阵的内容。 最后一行包含一个整数 targettarget

【输出格式】 输出一行,包含字符串 truefalse

【样例 1 输入】

3 4
1 3 5 7
10 11 16 20
23 30 34 60
3

【样例 1 输出】

true

【数据范围】

  • m==matrix.lengthm == matrix.length
  • n==matrix[i].lengthn == matrix[i].length
  • 1m,n1001 \le m, n \le 100
  • 104matrix[i][j],target104-10^4 \le matrix[i][j], target \le 10^4

二、 预备知识点

  1. 二分查找 (Binary Search):这是处理有序序列搜索的最快工具。
  2. 坐标转换/映射:在 1D 线性索引与 2D 矩阵坐标(行、列)之间建立数学对应关系。
  3. 单调性分析:识别题目给出的两个特点共同构成的“全局递增”性质。

三、 启发式思维引导

现在,请拿出你的草稿纸,跟着我的引导一步步推导:

第一步:观察矩阵的逻辑结构 在草稿纸上画出一个 3×33 \times 3 的矩阵,填入递增数字。 问:按照题目的描述,如果我把第一行写完,接着写第二行,再写第三行……这一长串数字是什么规律? :你会发现它们排成了一个完全有序的升序数组

第二步:抽象化处理 由于整个矩阵在逻辑上是一个有序数组,我们是否可以不把它看作矩阵,而看作一个长度为 L=m×nL = m \times n 的一维数组? 问:在这个长度为 LL 的一维数组中查找一个数,最优的时间复杂度是多少? O(log(m×n))O(\log(m \times n))

第三步:解决“索引转换”难题 假设一维数组的下标是 mid(范围 00m×n1m \times n - 1),如何找到它在二维矩阵中对应的 matrix[row][col]? 请在草稿纸上列出 n=4n=4 的情况:

  • mid=0(0,0)mid = 0 \Rightarrow (0, 0)
  • mid=3(0,3)mid = 3 \Rightarrow (0, 3)
  • mid=4(1,0)mid = 4 \Rightarrow (1, 0)
  • mid=7(1,3)mid = 7 \Rightarrow (1, 3) 推导公式
  • row = mid / n (利用整除获取行号)
  • col = mid % n (利用取模获取列号)

四、 算法复杂度分析思考

  1. 时间复杂度

    • 我们在 m×nm \times n 个元素中进行二分。
    • 每次判定只需要 O(1)O(1) 的坐标转换。
    • 总复杂度:O(log(m×n))O(\log(m \times n))
    • 优化建议:对于本题 100×100100 \times 100 的规模,这个复杂度远超要求(实际上 10610^6 级别都能轻松应对)。
  2. 空间复杂度

    • 我们只需要存储 left,right,midleft, right, mid 等常数个变量。
    • 复杂度:O(1)O(1)

五、 算法流程图 (Mermaid 语法)

以下是基于 C++14 标准逻辑实现的算法流程。注意图中避免了特殊符号导致的解析问题。

graph TD
    A(开始) --> B(获取矩阵行数m和列数n)
    B --> C(设置左边界 left 等于 0)
    C --> D(设置右边界 right 等于 m 乘 n 减 1)
    D --> E{left 小于等于 right}
    E -- 否 --> F(输出 false 并结束)
    E -- 是 --> G(计算中间值 mid)
    G --> H(计算对应行号 row 等于 mid 除以 n)
    H --> I(计算对应列号 col 等于 mid 取模 n)
    I --> J{matrix 所在位置的值等于 target}
    J -- 是 --> K(输出 true 并结束)
    J -- 否 --> L{matrix 所在位置的值小于 target}
    L -- 是 --> M(更新 left 等于 mid 加 1)
    L -- 否 --> N(更新 right 等于 mid 减 1)
    M --> E
    N --> E

六、 读题关键词总结

在 NOI 竞赛中,这类题目的题眼通常隐藏在以下词汇中:

  1. “每行……递增” & “第一行大于前一行最后一位”

    • 关键词:递增 (Sorted)、大于 (Greater than)。
    • 暗示:看到“有序”或“单调”,第一反应必须是二分查找
  2. m×nm \times n 矩阵”

    • 关键词:矩阵维度。
    • 暗示:需要注意边界处理,以及一维与二维下标的相互转换。
  3. “时间/空间限制”

    • 暗示:虽然本题数据范围小,但在大型比赛中,如果数据范围达到 10510^5,必须使用 O(logN)O(\log N) 算法,而不能使用 O(N)O(N) 的逐行遍历。

教练寄语:这道题是把“一维二分”披上了“二维矩阵”的外衣。学会透过现象看本质,寻找数据背后的单调性,是进阶金牌选手的必经之路!加油!