LCR 121. 寻找目标值 - 二维数组 【中等】
题目描述
m*n 的二维数组 plants 记录了园林景观的植物排布情况,具有以下特性:
- 每行中,每棵植物的右侧相邻植物不矮于该植物;
- 每列中,每棵植物的下侧相邻植物不矮于该植物。
请判断 plants 中是否存在目标高度值 target。
示例1
输入:plants = [[2,3,6,8],[4,5,8,9],[5,9,10,12]], target = 8
输出:true
示例2
输入:plants = [[1,3,5],[2,5,7]], target = 4
输出:false
限制:
0 <= n <= 1000
0 <= m <= 1000
Java代码
暴力解法
简单粗暴两层遍历挨个找。
class Solution {
public boolean findTargetIn2DPlants(int[][] plants, int target) {
for(int i = 0;i<plants.length;i++){
for(int j = 0;j<plants[0].length;j++){
if(plants[i][j]==target){
return true;
}
}
}
return false;
}
}
官方解法
从二维数组的右上角开始查找。如果当前元素等于目标值,则返回 true。如果当前元素大于目标值,则移到左边一列。如果当前元素小于目标值,则移到下边一行。
注意:可以证明这种方法不会错过目标值。如果当前元素大于目标值,说明当前元素的下边的所有元素都一定大于目标值,因此往下查找不可能找到目标值,往左查找可能找到目标值。如果当前元素小于目标值,说明当前元素的左边的所有元素都一定小于目标值,因此往左查找不可能找到目标值,往下查找可能找到目标值。
class Solution {
public boolean findTargetIn2DPlants(int[][] plants, int target) {
int i = plants.length-1;
int j = 0;
while(i>=0 && j<plants[0].length){
if(plants[i][j]<target){
j++;
}else if(plants[i][j]>target){
i--;
}else{
return true;
}
}
return false;
}
}
补充思路:
关键是要能够想到,从二维数组的右上角开始遍历。
- 因为左上和右下角分别是数组的最大值和最小值,所有有两个方向可以同时选择,无法确定唯一。
- 而左下和右上就可以,就拿右上角举例,它是行的最大值,列的最小值。如果它比目标值小,就可以排除这一行数据,列+1(因为它已经是这一行的最大值,比目标值还小,说明这一行数据都太小了,不可能有目标值。故列+1舍弃。)
还有另一种思路就是:
- 在右上角看。这个矩阵其实就像是一个Binary Search Tree二叉查找树。