avatar

剑指Offer-二维数组中的查找

📝题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

示例:

现有矩阵 matrix 如下:
[
[ 1, 4, 7, 11, 15],
[ 2, 5, 8, 12, 19],
[ 3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]

给定 target = 5,返回 true。
给定 target = 20,返回 false。

限制:
0 <= n <= 1000
0 <= m <= 1000


📝思路

暴力可行但效率低下,既然题目限定了“每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序”,不妨考虑根据这一性质在遍历过程中批量地排除数据。
第一次提交的想法是根据一行的头元素和尾元素来确定目标值可能存在的那些行,再在行范围内遍历,在某些情况下这种做法确实比暴力好得多,但并非最优做法。
参考官方题解可以知道,从二维数组的右上角开始查找:如果当前元素等于目标值,则返回 true。如果当前元素大于目标值,则移到左边一列。如果当前元素小于目标值,则移到下边一行。
注意容器大小为零的情况。

📝题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 第一次提交
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int outLen = matrix.size();
if (outLen == 0) return false;
int inLen = matrix[0].size();
if (inLen == 0) return false;
int maxIdx = 0, minIdx = 0;
for (int i = 0; i < outLen; ++i) {
if (matrix[i][inLen-1] == target || matrix[i][0] == target)
return true;
if (matrix[i][inLen-1] < target)
minIdx = i+1;
if (matrix[i][0] < target)
maxIdx = i;
}
for (int i = minIdx; i <= maxIdx; ++i) {
for (int j = 0; j < inLen; ++j) {
if (matrix[i][j] == target) {
return true;
}
}
}
return false;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 官方
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int outLen = matrix.size();
if (outLen == 0) return false;
int inLen = matrix[0].size();
if (inLen == 0) return false;
int row = 0, col = inLen - 1;
while (row < outLen && col >= 0) {
if (matrix[row][col] == target) return true;
else if (matrix[row][col] > target) col--;
else row++;
}
return false;
}
Author:WhiteBeerHouse
Link:https://github.com/WhiteBeerHouse/WhiteBeerHouse.github.io/tree/master/2021/02/01/%E5%89%91%E6%8C%87Offer-%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84%E4%B8%AD%E7%9A%84%E6%9F%A5%E6%89%BE/
Copyright Notice:All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.