热题100 - 74. 搜索二维矩阵

72 阅读2分钟

题目描述:

给你一个满足下述两条属性的 m x n 整数矩阵:

  • 每行中的整数从左到右按非严格递增顺序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。

示例 1:

输入: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出: true

示例 2:

输入: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出: false

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 100
  • -10^4 <= matrix[i][j], target <= 10^4

思路:

我有点搞不清楚74和另一个210的区别是什么。 我首先想到的是Z形搜索。 后面又实现了二分查找,分别是纵向和横向两种情况的二分查找。

实现:

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        // return zSearch(matrix, target);
        return bindarySearch(matrix, target);
    }

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

    private boolean bindarySearch(int[][] matrix, int target) {
        int m = matrix.length, n = matrix[0].length;
        // find which row it should belows to, use the last column
        int up = 0, down = m; // open right
        int mid;
        while (up < down) {
            mid = (up + down) >> 1;
            if (matrix[mid][n-1] == target) {
                return true;
            }
            if (matrix[mid][n-1] < target) {
                up = mid + 1;
            } else {
                down = mid; // open
            }
        }
        if (up == m) {
            return false;
        }
        int left = 0, right = n; // open
        while (left < right) {
            int mid2 = (left + right) >> 1;
            if (matrix[up][mid2] == target) {
                return true;
            }
            if (matrix[up][mid2] > target) {
                right = mid2;
            } else {
                left = mid2 + 1;
            }
        }
        return false;
    }
}

复杂度分析:

方法一:zSearch(逐行/列搜索)

时间复杂度分析
该方法从矩阵的右上角开始,每一步要么向左移动一列(j--),要么向下移动一行(i++)。在最坏情况下(例如目标位于左下角或不存在),需要遍历最多 m + n 步。因此,时间复杂度为 O(m + n),其中 m 是行数,n 是列数。

空间复杂度分析
仅使用固定数量的变量(i, j, m, n),不依赖输入规模,因此空间复杂度为 O(1)


方法二:binarySearch(二分查找)

时间复杂度分析

  1. 确定行:在最后一列进行二分查找,时间复杂度为 O(log m)
  2. 确定列:在目标行进行二分查找,时间复杂度为 O(log n)
    总时间复杂度为 O(log m + log n),等价于 O(log(mn))

空间复杂度分析
同样仅使用固定变量,空间复杂度为 O(1)


对比总结

zSearch 适合行列数接近的矩阵,但在大规模数据下效率较低。
binarySearch 利用二分特性,时间复杂度显著更优,尤其适合大规模矩阵。
• 两者空间复杂度均为 O(1),无显著差异。