【二分】搜索二维矩阵 Ⅱ
矩阵中的元素具有以下特性:
- 每行元素从左到右按升序排列;
- 每列元素从上到下按升序排列。
那我们如何利用这样的有序性高效查找 target 呢?
为了利用矩阵的有序性缩小搜索范围,我们希望每次比较当前元素与 target 后,都能排除一部分不可能包含目标值的区域。
观察矩阵的四个角,可以发现,左上角的元素是整个矩阵的最小值,右下角的元素是整个矩阵的最大值。
结合矩阵的行、列有序性,我们可以进一步观察右上角和左下角这两个位置。以右上角为例,可以发现,该位置的元素是所在行的最大值,同时也是所在列的最小值。
我们记右上角元素为 cur:
- 当
cur < target时,由于cur是所在行的最大值,该行所有元素都小于target,因此可以排除当前行。 - 当
cur > target时,由于cur是所在列的最小值,该列所有元素都大于target,因此可以排除当前列。 - 当
cur == target时,说明找到了目标值,直接返回true。
因此,从右上角开始搜索,就可以根据每次比较的结果,不断缩小搜索范围。排除一行或一列后,剩余区域仍然保持每行、每列有序的性质,因此可以继续按照上述方法搜索。
同理,左下角也具有类似的性质,因此也可以作为搜索起点。这里选择右上角进行说明。
我们从右上角出发,并使用变量 top 和 right 分别维护当前搜索区域的上边界和右边界。
每次比较后,根据上述规则移动对应边界,逐步缩小搜索范围。当搜索区域为空时,说明 target 不在矩阵中,返回 false。
基于这一思路,可写出如下代码:
▼java复制代码public boolean searchMatrix(int[][] matrix, int target) { int m = matrix.length, n = matrix[0].length; int top = 0, right = n - 1; while (top < m && right >= 0) { int cur = matrix[top][right]; if (cur == target) { return true; } else if (cur > target) { right--; } else { top++; } } return false; }
复杂度分析:
- 时间复杂度:$O(m+n)$。每次循环都会排除一整行或一整列,
top最多增加 $m$ 次,right最多减小 $n$ 次。 - 空间复杂度:$O(1)$。只使用了常数个额外变量。
评论
问答助学
相关内容
0个评论
全部评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
