/*
* 剑指 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]
]
给定 target=5,返回true。
给定 target=20,返回false。
*
* 思路:
* 方法一:暴力两轮循环,时间复杂度为(n*n),显然不是高效方法
* 方法二:
* 根据题意,左——>右递增和上——>下递增,则可判断当前位置上的 元素 一定是
* 大于 当前位置(行)的前一个元素 且 小于 当前位置(列) 的下一个元素
* 在初始原数组中,只有右上角的 元素 满足此条件。因此,可从右上角入手,依次往左或往下查找
* 1 初始化右上角元素的位置(行、列),开始循环查找
* 如果当前元素等于target,直接返回
* 2 如果当前元素大于target,说明当前列上所有元素都大于target
* 则可判断target不可能在当前列,往前一列找(列是从后往前)
* 3 如果当前数小于target,说明当前行上所有元素都小于target
* 则可判断target不可能在当前行,往下一行查找(行是从上到下)
* 4 如果查找完所有行列,都没有找到target,则不存在
* 复杂度分析:在循环中,访问到的下标的行的增加次数最多为n。所访问到的下标的列的减少次数最多为m
* 因此时间复杂度最大为 O(n+m)
* 空间复杂度为 O(1)
* */
public class _04 {
public static void main(String[] args) {
int[][] 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}};
boolean in2DArray = findNumberIn2DArray(matrix, 20);
System.out.println(in2DArray);
}
public static boolean findNumberIn2DArray(int[][] matrix, int target) {
// 如果二维数组为空,返回false
if (matrix==null || matrix.length==0 || matrix[0].length==0) return false;
// 二维数组行列
int rows = matrix.length;
int columns = matrix[0].length;
// 初始值(右上角的数,0行columns - 1列)
int row = 0;
int column = columns - 1;
// 从右上角循环遍历数组,查找target
while (row<rows && column>=0){
// 相等,直接返回true
if (matrix[row][column]==target){
return true;
// 如果当前数大于target
} else if (matrix[row][column]>target){
// 根据每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
// 则可判断target不可能在当前列,往前一列找(列是从后往前)
column--;
// 如果当前数小于target
} else {
// 根据左——>右递增和上——>下递增
// 则可判断target可能在当前行,往下一行查找(行是从上到下)
row++;
}
}
return false;
}
}