题目描述
给你一个满足下述两条属性的 m x n 整数矩阵 matrix:
-
每行中的整数从左到右按 非严格递增顺序 排列。
-
每行的第一个整数大于前一行的最后一个整数。
给你一个整数 target,如果 target 在矩阵中,返回 true;否则,返回 false。
示例 1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
示例 2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
提示:
-
m == matrix.length -
n == matrix[i].length -
1 <= m, n <= 100 -
-10^4 <= matrix[i][j], target <= 10^4
解题思路
题目给的两个条件说明了 矩阵可以看成一个整体递增的数组:
-
每行递增
-
下一行的第一个元素大于上一行最后一个元素
举例:
1 3 5 7
10 11 16 20
23 30 34 60
实际上等价于:
[1,3,5,7,10,11,16,20,23,30,34,60]
因此我们可以直接对这个"虚拟的一维数组"进行 二分查找。
下标转换公式
假设一维数组下标为 mid,对应二维矩阵下标为:
row = mid / n;
col = mid % n;
其中 n 为矩阵的列数。
C语言实现
#include <stdbool.h>
bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target) {
int m = matrixSize;
int n = matrixColSize[0];
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 val = matrix[row][col];
if (val == target) {
return true;
} else if (val < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return false;
}
复杂度分析
-
时间复杂度:O(log(m*n))
-
空间复杂度:O(1)
拓展
-
两次二分法:先在每一行的首元素中找出目标可能在哪一行,再在该行二分查找,复杂度为 O(log m + log n)。
-
LeetCode 240 搜索二维矩阵 II:矩阵只保证行、列递增,推荐从右上角或左下角开始搜索。
-
LeetCode 378 有序矩阵第 K 小元素:可以用二分查找答案或最小堆。