LeetCode 74. 搜索二维矩阵
题目描述


题意分析
在一个非空矩阵中判断目标值是否存在。每一行从左到右非递减,且下一行的第一个元素严格大于上一行的最后一个元素,因此上一行的所有值都小于下一行的所有值。
两条条件合在一起,意味着按行依次读取整个矩阵,就得到一个有序数组。题目要求对数时间,可以直接对这份“虚拟数组”进行二分,而不必真的复制矩阵元素。
解法:虚拟一维数组二分查找
核心思路
[!blue]
设矩阵有
m行、n列,一共m * n个位置。按行编号后,一维下标p前面有p / n个完整行,因此它所在的行是p / n,在当前行内的偏移是p % n。通过这两个值就能直接读取原矩阵,列数n才是每行的长度,不能换成行数。在闭区间
[left, right]中保存所有还可能包含目标的位置,初始范围是[0, m * n - 1]。取中点并换算行列坐标后,如果中点值等于目标,直接返回true。若中点值小于目标,由整体有序可知中点及其左侧都不可能命中,令
left = mid + 1;若中点值大于目标,则中点及其右侧都可以排除,令right = mid - 1。每轮都保留目标可能存在的一侧,同时严格缩小范围。当
left == right时仍有一个位置需要检查,因此使用left <= right。两者交错后候选区间为空,说明所有可能位置都已排除,返回false。整个过程只变化下标,非方阵也使用相同映射,不增加额外存储。
解题步骤
- 读取行列数,初始化
left = 0、right = m * n - 1。- 只要
left <= right,计算中点mid = left + (right - left) / 2。- 从
matrix[mid / n][mid % n]取得中点值。- 相等时返回
true;小于目标时移动左边界到mid + 1,大于目标时移动右边界到mid - 1。- 区间为空仍未命中时,返回
false。
代码实现
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
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 value = matrix[mid / n][mid % n];
if (value == target) {
return true;
}
if (value < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
}
func searchMatrix(matrix [][]int, target int) bool {
m, n := len(matrix), len(matrix[0])
left, right := 0, m*n-1
for left <= right {
mid := left + (right-left)/2
// 按列数将一维位置映射回行列,无需真的展平矩阵。
value := matrix[mid/n][mid%n]
if value == target {
return true
}
if value < target {
left = mid + 1
} else {
right = mid - 1
}
}
return false
}
复杂度分析
- 时间复杂度:$O(\log(mn))$,每轮将
m*n大小的搜索区间减半。- 空间复杂度:$O(1)$,只维护常数个下标变量。
关键点总结
[!green]
- 两条有序条件合在一起,才能保证按行展开后全局有序。
- 虚拟下标映射中的除数和模数都是列数
n。- 闭区间模板要配套使用:
right = m*n-1、left <= right、更新mid ± 1。- 240 题没有“下一行首元素大于上一行末元素”,不能使用整体二分。
易错点总结
[!yellow]
- 映射时使用行数:一维位置按每行的列数划分,行列转换都应使用
n,否则非方阵会读错位置或越界。- 右边界初始化为
m * n:闭区间末端必须是最后一个合法下标m * n - 1。- 循环漏掉等号:单元素候选区间仍需要检查。
- 更新为
left = mid或right = mid:中点已经确认不匹配,应排除它,否则区间可能无法继续缩小。- 实际展开矩阵或忽略跨行条件:复制数组需要线性时间和空间;只有行内有序、却没有跨行衔接条件时,也不能对整体二分。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 240. 搜索二维矩阵 II | 中等 | 原题仅保证行列分别有序,不能展平二分;本题还保证行与行整体相接有序。 |
| 35. 搜索插入位置 | 简单 | 展平后复用有序数组的下界或查找二分,最后把一维下标映射回行列。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!