74. 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵:

  • 每行中的整数从左到右按非严格递增顺序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false

示例 1:

img

1
2
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

示例 2:

img

1
2
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false

解法1:二分查找

由于矩阵具有特殊的有序性,可以将其视为一个有序的一维数组来处理:

  1. 整个矩阵可以看作是按行拼接而成的有序数组
  2. 使用二分查找高效定位目标值
  3. 通过计算将一维索引转换为二维矩阵的行和列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
if (matrix.empty() || matrix[0].empty()) {
return false;
}

int m = matrix.size(); // 行数
int n = matrix[0].size(); // 列数
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;
}
};

解法2:二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size(), n = matrix[0].size();
int left = -1, right = m * n;
while (left + 1 < right) {
int mid = left + (right - left) / 2;
int x = matrix[mid / n][mid % n];
if (x == target) {
return true;
}
(x < target ? left : right) = mid;
}
return false;
}
};

解法3:排除法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
bool searchMatrix(vector<vector<int>>& matrix, int target) {
int m = matrix.size(), n = matrix[0].size();
int i = 0, j = n - 1;
while (i < m && j >= 0) { // 还有剩余元素
if (matrix[i][j] == target) {
return true; // 找到 target
}
if (matrix[i][j] < target) {
i++; // 这一行剩余元素全部小于 target,排除
} else {
j--; // 这一列剩余元素全部大于 target,排除
}
}
return false;
}
};