LeetCode 74. 搜索二维矩阵
📌 题目描述
题目级别:中等
给你一个满足下述两条属性的 m x n 整数矩阵:
- 每行中的整数从左到右按非严格递增顺序排列。
- 每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。
- 示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]],target = 3
输出:true
💡 破题思路:降维打击,化二维为一维
这道题虽然披着"二维矩阵"的外衣,但由于它满足**"全局严格递增"(不仅行内递增,且下一行开头大于上一行结尾),我们可以直接对它实施降维打击**。
如果我们将这个 m 行 n 列的矩阵像拉面条一样拉直,它就是一个长度为 m * n 的严格单调递增的一维数组。既然是一维有序数组,那寻找目标值最快的方法毫无疑问就是二分查找。
本题核心:坐标映射魔法
在虚拟的一维数组中,我们二分出的中间索引是 mid。那么这个 mid 对应回真实的二维矩阵,它的行号和列号是多少呢?
假设矩阵有 n 列(每行有 n 个元素):
- 行号 :
mid / n(前面有几个完整的行) - 列号 :
mid % n(在当前行里排第几个)
我们不需要真的去开辟一个一维数组把数据拷出来,只需要在脑海中虚拟出这个一维数组,并在访问矩阵元素时套用这个公式即可!
💻 C++ 代码实现 (左闭右开二分模板)
cpp
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size(), n = matrix[0].size();
// 使用左闭右开区间 [0, m * n)
int l = 0, r = m * n;
while (l < r)
{
int mid = l + (r - l) / 2; // 防止溢出的标准写法 (原写法 (l+r)/2 逻辑上亦正确)
// 核心数学映射:一维索引转换为二维坐标
int mid_val = matrix[mid / n][mid % n];
if (mid_val == target) {
return true;
}
else if (mid_val < target) {
l = mid + 1; // 目标在右半边
}
else {
r = mid; // 目标在左半边,由于是右开区间,r 直接等于 mid
}
}
return false;
}
};