图解搜索二维矩阵:一次"数独探险"!
大家好,我是忍者算法。今天我要带大家攻克一道非常有趣的题目 - LeetCode 74「搜索二维矩阵」。这道题乍看有点唬人,但用我们玩数独游戏的思维去理解,你会发现它其实很优雅!
🎮 从数独游戏说起
还记得玩数独时,我们要在9×9的格子里查找数字吗?每次找数字时,我们都会先看这个数字可能在哪一行,然后再在那一行中定位。今天的题目就像是在玩一个简化版的数独,只不过格子里的数字是有规律排列的!
💡 问题本质探索
题目要求: 在一个m×n的矩阵中搜索一个目标值。这个矩阵有两个特点:
- 每行从左到右是升序的
- 每一行的第一个数都大于上一行的最后一个数
让我们看个具体例子:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 60]
]
target = 3
返回 true (因为3在矩阵中)🤔 深入思考
这个矩阵有什么特别之处?让我们仔细观察:
- 从左上角到右下角是严格递增的
- 把矩阵"拉直"后就是一个排序数组!
这个发现太关键了!它提示我们可以把二维搜索转化为一维搜索。
🚀 优雅的解决方案
java
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}
int m = matrix.length;
int n = matrix[0].length;
// 把二维坐标转换成一维来处理
int left = 0;
int right = m * n - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
// 关键转换:从一维索引还原二维坐标
int row = mid / n; // 行号
int col = mid % n; // 列号
int value = matrix[row][col];
if (value == target) {
return true;
} else if (value < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
}📝 解题思路全解析
1. 坐标转换的智慧
这个解法最精妙的地方在于坐标转换:
- 一维索引 = 行 × 列数 + 列
- 反过来:行号 = 一维索引 / 列数
- 列号 = 一维索引 % 列数
就像我们在实际生活中把二维的街道地址转换成一维的门牌号!
2. 二分查找的应用
有了坐标转换,问题就变成了普通的二分查找:
- 把矩阵看作一个长度为 m×n 的有序数组
- 用二分查找在这个"虚拟"的一维数组中搜索
- 需要时再把一维索引转回二维坐标
3. 边界处理
要特别注意以下边界情况:
- 矩阵为空
- 矩阵只有一行或一列
- 目标值在范围之外
💡 优化思维进阶
方案一:传统二分(上述方案)
时间复杂度:O(log(m×n)) 空间复杂度:O(1)
方案二:两次二分
可以先对第一列二分查找确定行,再在目标行中二分查找:
java
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
int n = matrix[0].length;
// 先二分查找第一列,确定目标所在行
int top = 0, bottom = m - 1;
while (top < bottom) {
int mid = (bottom + top + 1) / 2;
if (matrix[mid][0] <= target) {
top = mid;
} else {
bottom = mid - 1;
}
}
// 在目标行中二分查找
int row = top;
int left = 0, right = n - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (matrix[row][mid] == target) {
return true;
} else if (matrix[row][mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}🎯 相关题目引申
搜索二维矩阵 II(LeetCode 240)
- 类似但矩阵只保证行列有序
- 需要不同的搜索策略
有序矩阵中的第k小元素(LeetCode 378)
- 利用类似的矩阵性质
- 但需要结合二分查找和计数
🌟 面试常见追问
如何处理重复元素?
- 当前题目不涉及重复元素
- 但可以考虑查找第一个/最后一个位置
能否优化空间复杂度?
- 当前方案已经是O(1)空间复杂度
- 主要优化点在于减少不必要的计算
如果矩阵很大,如何优化?
- 考虑分块处理
- 可以使用并行计算
作者:忍者算法 公众号:忍者算法
🎁 回复【刷题清单】获取LeetCode高频面试题合集 🧑💻 回复【代码】获取多语言完整题解 💡 回复【加群】加入算法交流群,一起进步
#算法面试 #LeetCode #二分查找 #矩阵搜索