本溪市网站建设_网站建设公司_PHP_seo优化
2026/1/20 8:15:01 网站建设 项目流程

Java版LeetCode热题100之搜索二维矩阵:从基础到进阶的全面解析

本文将带你深入剖析 LeetCode 第74题「搜索二维矩阵」,通过多种解法、复杂度分析、面试技巧与实际应用,帮助你彻底掌握这道经典算法题。


一、原题回顾

题目描述(LeetCode 74. 搜索二维矩阵)

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

  1. 每行中的整数从左到右按非严格递增顺序排列(即升序,允许相等)。
  2. 每行的第一个整数大于前一行的最后一个整数

给你一个整数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

二、原题分析

这道题的关键在于理解矩阵的两个结构性质:

  1. 行内有序:每一行都是升序排列;
  2. 行间有序:第i行的首元素 > 第i-1行的尾元素。

这意味着整个矩阵可以被看作是一个全局升序的一维数组。例如:

[[1, 3, 5, 7], [10,11,16,20], [23,30,34,60]]

可视为一维数组:[1,3,5,7,10,11,16,20,23,30,34,60],完全升序。

因此,我们可以利用**二分查找(Binary Search)**这一高效算法来解决问题。

但如何在二维结构上进行二分?这是本题的核心挑战。


三、答案构思

思路一:两次二分查找(Two Binary Searches)

  • 第一步:在第一列中二分查找,确定target可能所在的行。
    • 因为每行首元素 > 上一行末元素 ⇒ 第一列也是升序。
    • 找到最后一个 ≤ target 的行首元素所在的行。
  • 第二步:在该行中进行标准二分查找,判断target是否存在。

✅ 优点:逻辑清晰,易于理解,适用于“行长度不一致”的变种题(虽然本题行长度一致)。

思路二:一次二分查找(Flatten Matrix)

  • 将整个m x n矩阵虚拟展开为长度为m*n的一维升序数组。
  • 对下标[0, m*n - 1]进行二分。
  • 利用数学映射:
    • 一维下标idx→ 二维坐标:row = idx / n,col = idx % n
  • 直接比较matrix[row][col]target

✅ 优点:代码简洁,效率高,充分利用了全局有序性。

两种方法时间复杂度相同,但实现思路不同,各有适用场景。


四、完整答案(Java 实现)

方法一:两次二分查找

classSolution{publicbooleansearchMatrix(int[][]matrix,inttarget){// Step 1: Find the candidate row using binary search on first columnintrowIndex=binarySearchFirstColumn(matrix,target);if(rowIndex<0){returnfalse;// No valid row found}// Step 2: Search within that rowreturnbinarySearchRow(matrix[rowIndex],target);}/** * 在矩阵的第一列中查找最后一个 <= target 的行索引 * 使用「右边界」二分模板(找 <= target 的最大值) */privateintbinarySearchFirstColumn(int[][]matrix,inttarget){intlow=-1;// 哨兵,表示无有效行inthigh=matrix.length-1;while(low<high){// 防止死循环:向上取整intmid=(high-low+1)/2+low;if(matrix[mid][0]<=target){low=mid;// 当前 mid 可能是答案,保留}else{high=mid-1;// 排除 mid}}returnlow;// 返回 [-1, m-1]}/** * 在指定行中进行标准二分查找 */privatebooleanbinarySearchRow(int[]row,inttarget){intlow=0,high=row.length-1;while(low<=high){intmid=(high-low)/2+low;if(row[mid]==target){returntrue;}elseif(row[mid]>target){high=mid-1;}else{low=mid+1;}}returnfalse;}}

方法二:一次二分查找(推荐)

classSolution{publicbooleansearchMatrix(int[][]matrix,inttarget){intm=matrix.length;intn=matrix[0].length;intlow=0;inthigh=m*n-1;while(low<=high){intmid=(high-low)/2+low;// 将一维索引映射回二维坐标introw=mid/n;intcol=mid%n;intvalue=matrix[row][col];if(value==target){returntrue;}elseif(value<target){low=mid+1;}else{high=mid-1;}}returnfalse;}}

💡 提示:方法二更简洁,且在 LeetCode 上通常运行更快(常数因子更小)。


五、代码分析

方法一详解

  • binarySearchFirstColumn

    • 使用的是寻找右边界的二分模板。
    • 初始化low = -1是为了处理target < matrix[0][0]的情况(此时应返回false)。
    • mid = (high - low + 1) / 2 + low是向上取整,避免low = mid导致死循环。
    • 最终low是满足matrix[low][0] <= target的最大行号。
  • binarySearchRow

    • 标准二分查找,无特殊处理。

方法二详解

  • 关键在于坐标映射
    • 一维下标idx ∈ [0, m*n-1]
    • 行号:idx / n(整除)
    • 列号:idx % n(取模)
  • 例如m=3, n=4,则:
    • idx=5row=5/4=1,col=5%4=1matrix[1][1]
  • 这种映射在内存连续存储(如 C/C++)中天然成立,在 Java 中虽为引用数组,但逻辑上完全等价。

六、时间复杂度和空间复杂度分析

方法时间复杂度空间复杂度说明
方法一(两次二分)O(log m + log n) = O(log(mn))O(1)先查行O(log m),再查列O(log n)
方法二(一次二分)O(log(mn))O(1)直接在mn个元素上二分

📌 注意:log m + log n = log(mn),所以两者渐近复杂度相同。

但由于方法二只有一次循环,常数更小,实际运行更快。


七、问题解答(常见疑问)

Q1:为什么方法一要找“最后一个 ≤ target 的行”?

因为矩阵性质保证:若target存在,它一定在第一个首元素 > target 的行的上一行中。

例如target=13,第一列为[1,10,23]10 ≤ 13 < 23,所以应在第1行(索引1)查找。

Q2:方法二是否要求每行长度相同?

是的!方法二依赖n = matrix[0].length作为固定列数进行坐标映射。

如果各行长度不同(如锯齿数组),则无法用idx / n计算行号。

⚠️ 但本题明确n == matrix[i].length,所以安全。

Q3:能否用线性搜索?

可以,但效率低:

  • 时间复杂度O(m + n)(从右上角开始走)或O(mn)(暴力遍历)。
  • 不符合“高效查找”的要求,面试中会被扣分。

八、优化思路

优化1:提前终止

在方法一中,若target < matrix[0][0]target > matrix[m-1][n-1],可直接返回false

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

但这在二分中已隐含处理,收益有限。

优化2:使用库函数(不推荐面试)

Java 的Arrays.binarySearch()可用于行内查找,但第一列仍需自定义二分。

intpos=Arrays.binarySearch(matrix[row],target);returnpos>=0;

但面试官更希望看到手写二分能力。

优化3:位运算加速(微优化)

mid = (low + high) >>> 1可防止溢出,但本题m,n ≤ 100,无需考虑。


九、数据结构与算法基础知识点回顾

1. 二分查找(Binary Search)

  • 前提:数组必须有序
  • 核心思想:每次排除一半搜索空间。
  • 模板
    • 查找目标值:while (low <= high)
    • 查找边界:while (low < high)+ 向上/向下取整

2. 二维数组的线性化

  • matrix[i][j]映射为一维下标:index = i * n + j
  • 反向映射:i = index / n,j = index % n
  • 应用于图像处理、矩阵压缩、内存布局等

3. 单调性与有序结构

  • 本题的“全局有序”是解题关键。
  • 类似结构:杨氏矩阵(Young Tableau),但本题更强(完全有序)。

4. 时间复杂度对数级别

  • O(log N)意味着每步问题规模减半。
  • 100万数据只需约20次比较!

十、面试官提问环节(模拟对话)

面试官:你用了两次二分,能不能只用一次?

回答:可以。因为整个矩阵是全局升序的,我们可以将其视为一维数组,通过idx → (row, col)映射,在[0, m*n-1]上做一次二分即可。

面试官:如果矩阵不是完全有序,只是每行每列分别有序(如左上到右下递增),还能用二分吗?

回答:不能直接用全局二分。但可以从右上角开始:

  • matrix[i][j] > target,则排除当前列(j--
  • matrix[i][j] < target,则排除当前行(i++
  • 时间复杂度O(m + n)

面试官:你的方法二在什么情况下会失效?

回答:当矩阵的行长度不一致时(如matrix = [[1,2], [3]]),无法用固定n进行坐标映射。此时方法一更鲁棒。

面试官:空间复杂度真的是 O(1) 吗?

回答:是的。我们只使用了几个整型变量(low,high,mid等),没有使用额外数组或递归栈,因此空间复杂度为常数。


十一、这道算法题在实际开发中的应用

1. 数据库存储引擎

  • B+树、LSM树等索引结构常将数据按页(Page)组织,每页内部有序,页间也有序。
  • 查找某条记录时,先定位页(类似找行),再在页内二分查找(类似找列)。

2. 分页缓存系统

  • 缓存按时间或ID分段存储,每段有序。
  • 快速判断某ID是否在缓存中,可用类似“两次二分”策略。

3. 图像/视频处理

  • 像素矩阵可视为二维数组,某些压缩算法依赖局部有序性。
  • 快速查找特定像素值的位置。

4. 游戏开发中的地图系统

  • 大型地图分块加载,每块内坐标有序。
  • 快速判断玩家是否进入某区域。

5. 日志分析

  • 日志按时间分文件,每个文件内按时间戳排序。
  • 查找某时间点的日志:先二分文件,再二分行。

十二、相关题目推荐

题目难度关联点
240. 搜索二维矩阵 II中等每行每列有序,但非全局有序
378. 有序矩阵中第 K 小的元素中等利用堆或二分答案
74. 搜索二维矩阵中等本题
1351. 统计有序矩阵中的负数简单利用有序性优化遍历
1428. 至少在两个数组中出现的值中等多数组二分

🔔 建议:先掌握本题,再挑战 240 题(更难,无全局有序性)。


十三、总结与延伸

核心收获

  1. 结构决定算法:矩阵的“全局有序”性质是使用二分查找的前提。
  2. 二维转一维:通过数学映射,将复杂结构简化为熟悉模型。
  3. 二分查找的灵活性:不仅可用于一维数组,还可用于“虚拟有序序列”。
  4. 鲁棒性 vs 简洁性:方法一更通用,方法二更高效,需根据场景选择。

延伸思考

  • 如果矩阵非常大(无法全加载到内存)?
    • 可结合外部排序思想,分块读取 + 二分定位块。
  • 如果允许重复元素?
    • 本题已允许(非严格递增),不影响解法。
  • 能否用分治或递归?
    • 可以,但不如二分高效,且空间复杂度可能上升。

最佳实践建议

  • 优先考虑方法二:代码短、效率高、易维护。
  • 掌握二分模板:尤其是边界处理(low < highvslow <= high)。
  • 面试时先说思路:强调“全局有序 → 虚拟一维数组 → 二分”。

结语

“搜索二维矩阵”看似简单,却蕴含了数据结构特性识别、算法模型转换、边界处理等多重考察点。掌握它,不仅能拿下 LeetCode 热题,更能培养你在面对复杂数据结构时的抽象与简化能力

正如计算机科学家 Edsger Dijkstra 所言:“简单是可靠的先决条件。” 通过将二维问题降维到一维,我们不仅找到了最优解,也体会到了算法之美。

练习建议:手写两遍代码,确保无 bug;尝试修改条件(如行长度不等),看解法是否仍适用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询