剑指 Offer 04. 二维数组中的查找#Java实现

103 阅读2分钟

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

解题思路

分析题目给出的条件——数组+有序,所以第一时间还是想到使用二分法来进行查找。

观察题目给出的条件,每一行都是从左到右的递增,每一列都是从上到下的递增。

  • 如果从左上角出发

    image-20220809220826077

    很明显,并不能确定target值大概在哪个方向,自然也不能用二分法来缩小查找的区间

  • 如果从右上角出发

    image-20220809221457661

    观察就能发现,如果从右上角向左下方向查找,刚好左边的值都比当前值小,右边的值都比当前值大,正好构成了一颗二叉查找树,现在使用二叉查找树的方式来遍历整个二维数组,时间复杂度为O(logN)

对角同理。

关键在于,从当前节点出发,需要满足一边递增、一边递减才能够使用二分法来缩小查找的区间

代码实现

从左上角出发

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if (matrix.length == 0) return false;
        int i = 0;
        int j = matrix[0].length - 1;
        while (i < matrix.length && j >= 0) {
            if (matrix[i][j] == target) return true;
            if (matrix[i][j] < target) {
                i++;
            } else {
                j--;
            }
        }
        return false;
    }
}

总结: 关键还是在于要理解二分法的本质,即通过不断缩小查找的区间来实现高效的查找。