牛客 BM18 二维数组中的查找
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]]
给定 target = 7,返回 true。
给定 target = 3,返回 false。
数据范围:矩阵的长宽满足 0 ≤ n,m ≤ 500 , 矩阵中的值满足 0 ≤ val ≤ 10^9
进阶:空间复杂度 O(1) ,时间复杂度 O(n+m)示例1
输入:
7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]返回值:
true说明:
存在7,返回true示例2
输入:
1,[[2]]返回值:
false示例3
输入:
3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]返回值:
false说明:
不存在3,返回false
解法一:暴力硬上
直接双重 for 循环,遍历数组,找到是否存在。可以简单优化,因为是向右下的递增,所以遇到大于 target 的就可以跳出该层循环;或者加个二分查找之类的。
for (i : 0 - n ) {
for (j : 0 - m ) {
if (nums[i][j] == target) {
return true;
}
}
return false;
解法二:分治(从题解看到的算法美学)
出发点:因为数组从左往右递增,从上往下递增,所以左下角的数字大于左上的数字,小于右下的数字。
解法:
1、获取数组边长,判断特殊情况
2、从左下角 A 出发,如果 A 大于 target,那么向上移动,如果 A 小于 target,向右移动
3、遇到边界仍未找到 target,说明数组不存在 target
示例:
1 | 2 | 8 | 9 | target=7 | |
2 | 4 | 9 | 12 | ||
4 | 7 | 10 | 13 | ||
6 | 8 | 11 | 15 |
首先获取左下角,A=6,A<target,所以 A 向右移动。这里需要注意,因为矩阵的递增性质,所以 A 这一列全都无法再次访问,因为他们都比 target 小。
1 | 2 | 8 | 9 | target=7 | |
2 | 4 | 9 | 12 | ||
4 | 7 | 10 | 13 | ||
6 | 8 | 11 | 15 |
获取 A=8,A>target,所以 A 向上移动。同理得 A=8 这一行全都失效,因为他们都比 target 大。
1 | 2 | 8 | 9 | target=7 | |
2 | 4 | 9 | 12 | ||
4 | 7 | 10 | 13 | ||
6 | 8 | 11 | 15 |
获得 A=7=target,结束方法。
int height = array.length;
int width = array[0].length;
int xPos = 0;
int yPos = height - 1;
while (yPos >= 0 && xPos < width) {
if (array[yPos][xPos] == target) {
return true;
} else if (array[yPos][xPos] > target) {
yPos--;
} else if (array[yPos][xPos] < target) {
xPos++;
}
}
return false;
还可优化,例如左下右上同时缩进等。