当前位置: 首页 > news >正文

深入解析二维矩阵搜索:LeetCode 74与240题的两种高效解法对比

文章目录

    • @[toc]
        • **引言**
      • **一、问题背景与排序规则对比**
        • **1. LeetCode 74. 搜索二维矩阵**
        • **2. LeetCode 240. 搜索二维矩阵 II**
      • **二、核心解法对比**
        • **方法1:二分查找法(适用于LeetCode 74)**
        • **方法2:线性缩小搜索范围法(适用于LeetCode 240)**
      • **三、关键差异与适用场景**
      • **四、为什么解法不能互换?**
        • **1. 二分查找法在LeetCode 240中的失效示例**
        • **2. 线性缩小法在LeetCode 74中的效率问题**
      • **五、边界情况处理**
        • **1. 空矩阵或空行**
        • **2. 单元素矩阵**
        • **3. 单行或单列矩阵**
      • **六、总结与建议**

引言

在算法面试中,二维矩阵搜索问题频繁出现,其中 LeetCode 74. 搜索二维矩阵LeetCode 240. 搜索二维矩阵 II 是两道经典的题目。尽管题目名称相似,但它们的矩阵排序规则和解题思路存在显著差异。本文将从问题本质出发,对比两种解法的核心思想、适用场景及实现细节,帮助读者深入理解并灵活应对类似问题。


一、问题背景与排序规则对比

1. LeetCode 74. 搜索二维矩阵
  • 题目描述
    在一个 m x n 的二维矩阵中,每一行元素严格递增,且下一行的第一个元素严格大于上一行的最后一个元素。要求判断目标值 target 是否存在于矩阵中。
  • 排序特性
    整个矩阵可以视为一个全局有序的一维数组,例如:
    [[1, 3, 5, 7],[10,11,16,20],[23,30,34,60]]
    
    展开后为一维数组:[1,3,5,7,10,11,16,20,23,30,34,60]
2. LeetCode 240. 搜索二维矩阵 II
  • 题目描述
    在一个 m x n 的二维矩阵中,每一行元素从左到右递增,每一列元素从上到下递增,但行与行之间没有严格的大小关系。要求判断目标值是否存在。
  • 排序特性
    矩阵仅局部有序,无法直接展开为全局有序的一维数组,例如:
    [[1, 4, 7],[2, 5, 8],[3, 6, 9]]
    

二、核心解法对比

方法1:二分查找法(适用于LeetCode 74)
  • 核心思想
    将二维矩阵映射为一维数组,利用二分查找直接定位目标值。

  • 时间复杂度
    (O(\log(m \times n))),其中 (m) 为行数,(n) 为列数。

  • 实现步骤

    1. 将二维索引映射为一维:index = row * n + col
    2. 通过一维索引的二分查找确定目标值的位置。
    3. 转换回二维索引进行值比较。
  • Java代码实现

    class Solution {public boolean searchMatrix(int[][] matrix, int target) {if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;int m = matrix.length, n = matrix[0].length;int left = 0, right = m * n - 1;while (left <= right) {int mid = left + (right - left) / 2;int row = mid / n;  // 计算行坐标int col = mid % n;  // 计算列坐标if (matrix[row][col] == target) {return true;} else if (matrix[row][col] < target) {left = mid + 1;} else {right = mid - 1;}}return false;}
    }
    
方法2:线性缩小搜索范围法(适用于LeetCode 240)
  • 核心思想
    从矩阵的右上角(或左下角)出发,通过逐步排除行或列缩小搜索范围。

  • 时间复杂度
    (O(m + n)),其中 (m) 为行数,(n) 为列数。

  • 实现步骤

    1. 初始化位置为右上角 (0, n-1)
    2. 若当前值等于目标值,返回 true
    3. 若当前值大于目标值,向左移动一列;否则向下移动一行。
    4. 重复直至越界。
  • Java代码实现

    class Solution {public boolean searchMatrix(int[][] matrix, int target) {if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;int m = matrix.length, n = matrix[0].length;int row = 0, col = n - 1;  // 从右上角开始搜索while (row < m && col >= 0) {int current = matrix[row][col];if (current == target) {return true;} else if (current > target) {col--;  // 排除当前列} else {row++;  // 排除当前行}}return false;}
    }
    

三、关键差异与适用场景

对比维度二分查找法(LeetCode 74)线性缩小法(LeetCode 240)
时间复杂度(O(\log(mn)))(对数级,高效)(O(m + n))(线性级,适用于中等规模矩阵)
空间复杂度(O(1))(原地操作)(O(1))(原地操作)
排序规则依赖必须全局有序仅需局部行列有序
适用题目仅LeetCode 74仅LeetCode 240(但LeetCode 74也可用)
优势场景大规模全局有序矩阵局部有序或中等规模矩阵

四、为什么解法不能互换?

1. 二分查找法在LeetCode 240中的失效示例
  • 矩阵示例
    [[1, 3, 5],[2, 4, 6],[7, 8, 9]
    ]
    
  • 搜索目标2
    • 一维展开为 [1,3,5,2,4,6,7,8,9],二分查找时中间值可能跳过实际存在的元素,导致错误结果。
2. 线性缩小法在LeetCode 74中的效率问题
  • 矩阵示例
    [[1, 3, 5, 7],[10,11,16,20],[23,30,34,60]
    ]
    
  • 搜索目标60
    • 从右上角开始需遍历 7 → 20 → 60,时间复杂度为 (O(n)),而二分查找仅需 (O(\log 12) \approx 4) 次比较。

五、边界情况处理

1. 空矩阵或空行
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;
2. 单元素矩阵
  • 矩阵为 [[5]],目标值为 5 时直接返回 true
3. 单行或单列矩阵
  • 单行矩阵 [[1,3,5]] 或单列矩阵 [[2],[4],[7]],两种方法均能正确处理。

六、总结与建议

  1. LeetCode 74(全局有序)

    • 优先选择二分查找法,时间复杂度更低,适合大规模数据。
    • 若使用线性缩小法,虽然可行,但效率略低。
  2. LeetCode 240(局部有序)

    • 必须使用线性缩小法,二分查找法因全局无序可能失效。
    • 从右上角或左下角出发均可,逻辑对称。
  3. 实际应用场景

    • 数据库索引查询(全局有序场景)。
    • 图像处理中的局部特征搜索(局部有序场景)。

通过深入理解矩阵的排序规则与算法特性,读者可以灵活选择最优解法,轻松应对二维矩阵搜索问题。无论是面试还是实际工程应用,清晰的思路和高效的代码实现都是解决问题的关键。

http://www.xdnf.cn/news/298675.html

相关文章:

  • 【C++游戏引擎开发】第31篇:物理引擎(Bullet)—碰撞检测系统
  • 质量员考试案例题有哪些常见考点?
  • K8S PV 与 PVC 快速开始、入门实战
  • C++负载均衡远程调用学习之集成测试与自动启动脚本
  • Spark,所用几个网页地址
  • PaddlePaddle 和PyTorch选择与对比互斥
  • NSSM 完全指南:如何将任意程序部署为 Windows 服务
  • OpenHarmony GPIO应用开发-LED
  • 搭建一个简单的博客界面(前端HTML+CSS+JS)
  • 《AI大模型应知应会100篇》第50篇:大模型应用的持续集成与部署(CI/CD)实践
  • 互联网大厂Java求职面试:AI与云原生下的系统设计挑战-3
  • K8S有状态服务部署(MySQL、Redis、ES、RabbitMQ、Nacos、ZipKin、Sentinel)
  • 【JsonCpp、Muduo、C++11】JsonCpp库、Muduo库、C++11异步操作
  • Jenkins 改完端口号启动不起来了
  • IoTDB磁盘I/O性能监控与优化指南
  • Caffeine快速入门
  • Oracle02-安装
  • JavaScript 对象引用与值传递的奥秘
  • Acrel-EIoT 能源物联网云平台在能耗监测系统中的创新设计
  • 启发式算法-模拟退火算法
  • STM32的智慧农业系统开发(uC/OS-II)
  • 如何设计Kafka的高可用跨机房容灾方案?(需要实战,未实战,纯理论)
  • 破局者手册 Ⅱ:测试开发深度攻坚,引爆质量优化新动能!
  • ES6/ES11知识点 续四
  • 【自然语言处理与大模型】LlamaIndex的词嵌入模型和向量数据库
  • 奇瑞依托汽车产业链,实现服务机器人万台下线
  • 【计算机网络 第8版】谢希仁编著 第四章网络层 地址类题型总结
  • 前端-HTML+CSS+JavaScript+Vue+Ajax概述
  • UE5 诺伊腾动捕使用笔记
  • Vue + Element UI 表单弹窗输入法卡顿问题解决方案