剑指Offer_#4_二维数组中的查找

剑指Offer_#4_二维数组中的查找

Contents

题目

在一个 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

思路分析

方法1:暴力搜索

两轮循环,暴力搜索,可以通过,但是因为没有利用到题目给出的条件“每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序”,所以肯定不是最优解。

方法2:从右上角(左下角)开始查找

最自然的想法肯定是从左上角开始遍历矩阵,但是如果从左上角开始遍历,是没法利用到题目条件来优化算法的,因为从左上到右下,无论向下走还是向右走,数字都是增大,无法进行决策。
但是如果从右上角开始向左下角查找,我们发现,向左走数字减小,向下走数字增大。那么其实就是类似于在二叉搜索树查找一个数字

  • 如果当前数字小于target,则向下移动,排除当前行
  • 如果当前数字大于target,则向左移动,排除当前列

这样就可以不用遍历所有的数字。因为每次移动的时候,就相当于排除掉一行或者一列,时间复杂度变成O(m+n)。
同理,从左下角开始查找也是类似的,不再赘述。

解答

解答1:暴力搜索

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0)
            return false;
        for(int i = 0;i < matrix.length;i++){
            for(int j = 0;j < matrix[i].length;j++){
                if(matrix[i][j] == target) return true;
            }
        }
        return false;
    }
}

复杂度分析

时间复杂度:O(n2)
空间复杂度:O(1)

关于数组和null

  1. 数组不属于java的基本类型,属于对象。
  2. 基本类型只有 boolean, byte, short, char, int, long, float, double 8种。
  3. null只可以赋值给对象的引用变量,不可以赋值给基本类型变量。

所以本题中考虑的特殊情况,不仅仅要考虑数组长度为0的情况,还要考虑输入为null值的情况。

解答2:从右上角开始查找

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if(matrix == null || matrix.length == 0 || matrix[0].length == 0)
            return false;
        int rows = matrix.length;
        int cols = matrix[0].length;
        //从右上角元素开始查找
        int row = 0;
        int col = cols - 1;
        //循环条件是不超出matrix坐标范围
        while(row <= rows - 1 && col >= 0){
            if(matrix[row][col] == target) return true;
            //ERROR:下面两句不可以写成if,否则col--之后可能已经越界了,到最后一个判断语句就会出现越界
            else if(matrix[row][col] > target) col--;
            else if(matrix[row][col] < target) row++;
        }
        //循环结束了还没有找到target,就返回false
        return false;
    }
}

复杂度分析

时间复杂度:O(m+n)
空间复杂度:O(1)

posted @ 2020-07-30 19:10  Howfar's  阅读(232)  评论(0编辑  收藏  举报