从零开始写算法——二分-搜索二维矩阵
题目简述
二维矩阵满足:
每一行从左到右递增
每一行首元素大于上一行最后一个元素
这意味着矩阵整体呈现严格递增的一维序列。
例如:
[[1, 3, 5, 7],[10,11,16,20],[23,30,34,60]
]
可以视为:
1,3,5,7,10,11,16,20,23,30,34,60
核心思想:二维转一维
二维矩阵按行拼接,即坐标映射:
i → (i / n, i % n)
其中:
n是列数i / n是行号i % n是列号
二分查找代码(闭区间写法)
class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int m = matrix.size();int n = matrix[0].size();int left = 0;int right = m * n - 1; // 一维区间 [0, m*n-1]while (left <= right) {int mid = left + (right - left) / 2;// mid / n → 行// mid % n → 列if (matrix[mid / n][mid % n] < target) {left = mid + 1;} else {right = mid - 1;}}// 💥 关键:避免越界访问 matrix[left]if (left == m * n) return false;return matrix[left / n][left % n] == target;}
};
重点:闭区间二分为什么会越界?
闭区间写法:
left = 0
right = size-1
while (left <= right)
这一写法的返回值有一个特点:
最终的 left 可能等于 size
这是完全符合设计的,因为:
如果所有元素都小于 target
⇒ 返回应该是第一个大于等于 target 的位置
⇒ 也就是 size
⇒ left == size
但问题来了:
你一旦直接访问:
nums[left]
若 left == size:
nums[size] // 非法访问,越界 ❌
如何避免越界?
只要使用闭区间写法,就必须判断:
if (left == size) return ...
总结
闭区间写法凡是涉及到访问nums[size]一定要注意边界访问越界问题。
二维搜索矩阵的核心:
把矩阵视为一维递增数组
用
mid / n、mid % n完成坐标映射
闭区间写法最大的坑:
最终 left 可能等于数组长度(size),访问会越界
所以必须判断:
if (left == size) return ...;
为什么需要判断?
因为
left = size是合法返回值,但不是合法下标
