JZ04 二维数组中的查找

116 阅读1分钟

leetcode.cn/problems/er…

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

解题思路:

若使用暴力法遍历矩阵 matrix ,则时间复杂度为 O(NM) 。暴力法未利用矩阵 “从上到下递增、从左到右递增” 的特点,显然不是最优解法。

如下图所示,我们将矩阵逆时针旋转 45° ,并将其转化为图形式,发现其类似于 二叉搜索树 ,即对于每个元素,其左分支元素更小、右分支元素更大。因此,通过从 “根节点” 开始搜索,遇到比 target 大的元素就向左,反之向右,即可找到目标值 target 。

image.png

image.png

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if (matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }
        int n = matrix.length;
        int m = matrix[0].length;

        int i = n - 1, j = 0;
        while (i >= 0 && j <= m - 1) {
            if (matrix[i][j] == target) {
                return true;
            }
            if (matrix[i][j] > target) {
                i--;
            } else if (matrix[i][j] < target) {
                j++;
            }
        }
        return false;
    }
}

方法二:剪枝暴力法

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if (matrix.length == 0 || matrix[0].length == 0) {
            return false;
        }
        int n = matrix.length;
        int m = matrix[0].length;

        if (target < matrix[0][0] || target > matrix[n - 1][m - 1]) {
            return false;
        }

        int i = 0, j = n - 1, targetN = 0;

        while (i < n || j > 0) {
            if (matrix[i][0] == target || matrix[j][0] == target) {
                return true;
            }
            if (matrix[i][0] < target) {
                i++;
            } else {
                targetN = --i;
                break;
            }

            if (matrix[j][0] > target) {
                j--;
            } else {
                targetN = j;
                break;
            }
        }


        i = 0;
        j = m - 1;
        int targetM = 0;
        while (i < m || j > 0) {
            if (matrix[0][i] == target || matrix[0][j] == target) {
                return true;
            }

            if (matrix[0][i] < target) {
                i++;
            } else {
                targetM = --i;
                break;
            }

            if (matrix[0][j] > target) {
                j--;
            } else {
                targetM = j;
                break;
            }
        }

        for (int p = 1; p <= targetN; p++) {
            for (int q = 1; q <= targetM; q++) {
                if (matrix[p][q] == target) {
                    return true;
                }
            }
        }
        return false;
    }
}