剑指 Offer 04. 二维数组中的查找

147 阅读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。

来源:力扣(LeetCode)

链接:leetcode-cn.com/problems/er…

思路

把这个矩阵从右上角看向左下角,跟二叉搜索树的结构很像。所以可以把这个矩阵近似看成二叉搜索树。这样的思路就很清晰了。

我第一次做没想出来,就直接暴力了,这道题通过后看了下评论区老哥的一句话,恍然大悟,用二叉搜索树的做法,执行用时超越100%的用户了。

这位老哥是这样说的:

提一个不太有人讲的观点,站在右上角看。这个矩阵其实就像是一个Binary Search Tree。然后,聪明的大家应该知道怎么做了。

题解

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        return answer2(matrix, target);
    }
    // 暴力法
    private boolean answer1(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 || 
            matrix[0] == null || matrix[0].length == 0)
            return false;
        List<Integer> numbers = new ArrayList<>(matrix.length * matrix[0].length);
        for (int[] row : matrix) {
            for (int e : row) {
                numbers.add(e);
            }
        }
        Collections.sort(numbers);
        return Collections.binarySearch(numbers, target) >= 0;
    }

    private int xMax;
    private int yMax;
    // 受到评论区老哥的启发,用二叉树搜索做
    private boolean answer2(int[][] matrix, int target) {
        if (matrix == null || matrix.length == 0 || 
            matrix[0] == null || matrix[0].length == 0)
            return false;
        xMax = matrix.length;
        yMax = matrix[0].length;
        int x = 0, y = yMax - 1;
        while (checkRange(x,y)) {
            if (target < matrix[x][y]) {
                // 小于就遍历左子树(当成二叉搜索树来看)
                y--;
            } else if (target > matrix[x][y]) {
            	// 大于就遍历右子树
                x++;
            } else {
                return true;
            }
        }
        return false;
    }

    private boolean checkRange(int x, int y) {
        return x >= 0 && y >= 0 && x < xMax && y < yMax;
    }
}