# 二维数组中的查找(剑指Offer 04)
# 题目
在一个 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]
]
1
2
3
4
5
6
7
2
3
4
5
6
7
给定 target = 5
,返回 true
。
给定 target = 20
,返回 false
。
# 限制
- 0 <= n <= 1000
- 0 <= m <= 1000
# 算法
# 二分查找
因为是行和列都是排序的,我们可以使用二分查找
当当前行首尾的范围包括targer
,我们在当前行中使用二分查找寻找目标target
当当前行的末尾元素小于target
,我们直接返回false
export const findNumberIn2DArray = (matrix, target) => {
if (!matrix.length || !matrix[0].length) return false;
let start, end;
for (let i = 0; i < matrix.length; i++) {
start = 0;
end = matrix[0].length - 1;
if (matrix[i][start] > target) return false;
if (matrix[i][start] <= target && matrix[i][end] >= target) {
while (start <= end) {
const mid = ~~((start + end) / 2);
if (matrix[i][mid] === target) return true;
else if (matrix[i][mid] > target) end = mid - 1;
else if (matrix[i][mid] < target) start = mid + 1;
}
}
}
return false;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 线性查找
初始化一个指针指向右上角,将整个二维数组看作一个二叉搜索树(BST):二维数组的每一项的左边(看作左子树)都是小于它的值,每一项下面(看作右子树)都是大于它的值
- 如果当前指针指向值等于
target
,直接返回true
- 如果当前指针指向值小于
target
,行row++
- 如果当前指针指向值大于
target
,列col--
- 如果指针越界
row >= matrix.length
或col < 0
,返回false
这种查找方法一定不会错过目标值target
:
- 如果当前值小于
target
,那么当前值左侧一定都小于target
,只能行row++
向下查找 - 如果当前值大于
target
,那么当前值下面一定都大于target
,只能列col--
向左查找
export const findNumberIn2DArray = (matrix, target) => {
if (!matrix.length || !matrix[0].length) return false;
let row = 0,
column = matrix[0].length - 1;
while (row < matrix.length && column >= 0) {
const cur = matrix[row][column];
if (cur === target) return true;
else if (cur < target) row++;
else if (cur > target) column--;
}
return false;
};
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
← 寻找峰值(162) 搜索二维矩阵(74) →