#LC240. 搜索二维矩阵 II
搜索二维矩阵 II
你好!我是教练。在攻克了“搜索二维矩阵 I”之后,我们迎来了它的进阶版——搜索二维矩阵 II。
这一题在 NOI 竞赛中属于典型的**双指针(维护单调性)**应用。虽然它和第一题名字很像,但矩阵的性质发生了微妙的变化,导致我们的解法需要从“一维映射”转化为“单调边界移动”。
一、 题目描述 (NOI 竞赛格式)
题目名称:搜索二维矩阵 II (Search a 2D Matrix II)
文件输入:matrix.in
文件输出:matrix.out
时间限制:1.0s
内存限制:256MB
【问题描述】
编写一个高效的算法来搜索 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:
- 每行的元素从左到右升序排列。
- 每列的元素从上到下升序排列。
【输入格式】 第一行包含两个整数 和 ,表示矩阵的行数和列数。 接下来 行,每行包含 个整数,表示矩阵的内容。 最后一行包含一个整数 。
【输出格式】
如果目标值存在,输出字符串 true;否则,输出 false。
【样例 1 输入】
5 5
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
5
【样例 1 输出】
true
【数据范围】
二、 预备知识点
- 单调性搜索:利用行和列同时具备的递增性质。
- 双指针/排除法:通过当前值与目标值的比较,每次排除掉一行或一列。
- 决策点选择:在矩阵中寻找具有“分叉路口”特征的特殊位置。
三、 启发式思维引导
请拿出草稿纸,我们换一种思路来“切”这个矩阵。
第一步:观察性质的局限性 在第一题中,矩阵是全局有序的,像一根拉长的绳子。但在本题中,绳子断了,变成了每一行有序,每一列也有序。
- 思考:如果你站在左上角 ,发现
matrix[0][0] < target,你应该往右走还是往下走? - 反馈:右边比它大,下边也比它大。两个方向都有可能存在 target,这会产生递归分支,不够高效。
第二步:寻找特殊的“决策角”
我们要找一个位置,使得当我们比较 current 和 target 时,下一步的移动方向是唯一的。
- 观察右上角 :
- 它的左边元素全比它小(行单调)。
- 它的下边元素全比它大(列单调)。
- 问:如果
matrix[0][n-1] > target,target 可能在它的下方吗? - 答:不可能,因为下方只会更大。所以我们可以放心地排除掉最后一列。
- 问:如果
matrix[0][n-1] < target,target 可能在它的左方吗? - 答:不可能,因为左边只会更小。所以我们可以放心地排除掉第一行。
第三步:模拟路径 在草稿纸上画一个矩形,从右上角开始,像下楼梯一样,要么向左移,要么向下移。每一次移动都把搜索范围缩小了一行或一列。
- 这种走法被称为“Z字形搜索”或“阶梯搜索”。
四、 复杂度分析思考过程
-
时间复杂度:
- 我们从右上角出发,最远要走到左下角。
- 每次比较,要么
row++,要么col--。 - 最多移动 次。
- 复杂度:。
- 优化建议:对于 的规模, 仅需 600 次计算,而暴力法需要 90,000 次。这种线性增长的优势在 很大时非常恐怖。
-
空间复杂度:
- 只需要维护两个指针
r和c。 - 复杂度:。
- 只需要维护两个指针
五、 算法流程图 (Mermaid 语法)
由于 Mermaid 中特殊字符容易报错,我将使用全文字描述逻辑:
graph TD
Start(开始) --> GetMN(获取行数m和列数n)
GetMN --> InitPointer(初始化指针: 行 r 等于 0, 列 c 等于 n 减 1)
InitPointer --> LoopCond{r 小于 m 并且 c 大于等于 0}
LoopCond -- 否 --> NotFound(输出 false 并结束)
LoopCond -- 是 --> GetVal(获取当前位置值 val)
GetVal --> Compare{val 与 target 的关系}
Compare -- 等于 --> Found(输出 true 并结束)
Compare -- 大于 --> MoveLeft(目标在左侧: c 减 1)
Compare -- 小于 --> MoveDown(目标在下方: r 加 1)
MoveLeft --> LoopCond
MoveDown --> LoopCond
六、 读题关键词总结
-
“每行升序” & “每列升序”:
- 关键词:同时满足两个维度的单调性。
- 暗示:这通常对应 的双指针解法,或者是对每一行进行二分查找的 解法。
-
“高效算法”:
- 暗示:题目暗示 的暴力遍历在更大的数据下可能无法通过,需要利用有序性。
-
对比“I”与“II”:
- 关键点:看有没有“下一行首大于上一行末”。如果有,用全局二分;如果没有,用阶梯搜索。
教练寄语: 在 NOI 竞赛中,右上角和左下角往往是处理二维矩阵单调性问题的“神级起点”。这种“排除法”的思想不仅能解矩阵搜索,在很多寻找有序组合(如两数之和、三数之和)的问题中也有异曲同工之妙。多在草稿纸上画方向箭头,规律自然显现!