LEETCODE 240Medium
搜索二维矩阵 II
站在右上角,这个矩阵就是一棵二叉搜索树:往左变小,往下变大,每次比较排除一行或一列。
问题拆解
矩阵每行从左到右递增、每列从上到下递增,问 target 在不在里面。暴力扫全表是 O(mn);对每一行做二分是 O(m log n),好一些,但它只用上了“行有序”,列方向的有序性完全浪费了。
想同时用上两个方向的有序性,就要找一个特殊的起点。右上角就是这样的位置:它是所在行的最大值,又是所在列的最小值。拿它和 target 比较,无论结果如何都能得到确定的结论——如果它比 target 大,那它下方整列都更大,这一列可以整体划掉;如果它比 target 小,那它左边整行都更小,这一行可以整体划掉。
右上角看出去,往左递减、往下递增——这正是一棵二叉搜索树的形状。每次比较砍掉一整行或一整列,搜索路径最长
m + n步。
从右上角出发的阶梯搜索
public boolean searchMatrix(int[][] matrix, int target) {
int i = 0, j = matrix[0].length - 1; // 从右上角出发
while (i < matrix.length && j >= 0) {
if (matrix[i][j] == target) {
return true;
} else if (matrix[i][j] > target) {
j--; // 这一列都比 target 大,左移
} else {
i++; // 这一行都比 target 小,下移
}
}
return false;
}
def searchMatrix(matrix: List[List[int]], target: int) -> bool:
i, j = 0, len(matrix[0]) - 1 # 从右上角出发
while i < len(matrix) and j >= 0:
if matrix[i][j] == target:
return True
elif matrix[i][j] > target:
j -= 1 # 这一列都比 target 大,左移
else:
i += 1 # 这一行都比 target 小,下移
return False
func searchMatrix(matrix [][]int, target int) bool {
i, j := 0, len(matrix[0])-1 // 从右上角出发
for i < len(matrix) && j >= 0 {
switch {
case matrix[i][j] == target:
return true
case matrix[i][j] > target:
j-- // 这一列都比 target 大,左移
default:
i++ // 这一行都比 target 小,下移
}
}
return false
}
pub fn search_matrix(matrix: Vec<Vec<i32>>, target: i32) -> bool {
let mut i = 0usize;
let mut j = matrix[0].len() as i32 - 1; // 列用 i32,允许减到 -1
while i < matrix.len() && j >= 0 {
let v = matrix[i][j as usize];
if v == target {
return true;
} else if v > target {
j -= 1; // 这一列都比 target 大,左移
} else {
i += 1; // 这一行都比 target 小,下移
}
}
false
}
起点的选择只有右上角和左下角可行。左上角不行:它是全局最小,target 比它大时行列两个方向都可能,比较不产生任何排除。指针的移动是单向的——i 只增、j 只减,所以循环最多执行 m + n 次,不会回头也不会死循环。Rust 版把列下标声明成 i32,是为了让 j 能自然减到 -1 结束循环,避免 usize 下溢。
复杂度
| 指标 | 复杂度 | 原因 |
|---|---|---|
| 时间 | O(m + n) |
每次比较让 i 或 j 单向前进一步 |
| 空间 | O(1) |
只用两个下标 |
可以迁移的模式
- 在多维有序结构里找一个“比较结果能给出确定方向”的观察点,右上角、左下角这类极值角往往就是;
- 两个指针各自单调移动,总步数就是它们行程之和,复杂度一眼可知;
- 把矩阵视作隐式二叉搜索树,是“换个视角结构就显形”的典型例子。
第 74 题“搜索二维矩阵”的行间也有序,可以整体二分到 O(log mn);本题行间无序,阶梯搜索就是最优雅的答案。