hot100 搜索二维矩阵(74)
本题采用虚拟一维二分查找算法解决行列递增矩阵的目标值检索问题。其核心本质是利用矩阵行的首尾单调连续性将二维网格在逻辑上拉平为一维严格有序序列通过一维索引与二维坐标的数学映射实现对数阶的二分剪枝。当前提供的源码实现了在时间复杂度 O(log(m * n)) 和额外空间复杂度 O(1) 条件下的全局最优检索最终走向是精准判定目标值是否存在于矩阵中。一、 问题本质与数据模型对于大小为 m x n 的二维矩阵 matrix题目给出了两个核心的单调性约束每行元素从左到右非严格递增排列matrix[i][j] matrix[i][j1]行的首元素大于前一行的尾元素matrix[i][0] matrix[i-1][n-1]这两个约束共同作用使该二维矩阵在逻辑上具备了全局的一维单调递增属性。即如果将矩阵的每一行首尾相连将退化为一个完全有序的一维数组。为了破除多维数组索引定位的物理阻隔算法引入了“坐标虚拟映射模型”。将包含 m * n 个元素的矩阵视为长度为 m * n - 1 的一维虚拟数组其任意一维线性索引 mid 可以通过确定的数学公式完美映射回二维矩阵的物理坐标行坐标映射row mid / n整除操作确定元素位于第几行列坐标映射col mid % n取模操作确定元素位于当前行的第几列这种拓扑映射将二维空间检索直接转化为经典的一维二分查找使得每次中点比对都能直接剔除当前虚拟序列的一半元素。二、 算法演进对比在解决全局有序矩阵的检索问题时虚拟一维二分查找法在时间效率上达到了理论极限解法名称时间复杂度空间复杂度核心原理物理瓶颈 / 缺陷全矩阵暴力枚举O(m * n)O(1)双重循环逐个扫描矩阵中的每一个单元格完全没有利用任何单调性先验条件算力大量浪费阶梯搜索法对角隅角剪枝O(m n)O(1)从右上角出发利用单调性每步消除一行或一列适用于行列独立递增但行尾与次行首无连续性的矩阵在此场景下未达到对数阶的极致效率虚拟一维二分查找当前解法O(log(m * n))O(1)将二维索引虚拟映射为一维序列执行标准对数二分剪枝强依赖“行尾小于次行首”的全局连续性约束若约束失效则无法拉平映射三、 核心分支控制逻辑与决策证明当前源码的控制流完全依赖于 while (left right) 所构建的区间边界防护网其内部决策分支证明如下1. 命中分支if (matrix[row][col] target)执行直接返回 true。物理意义经映射变换后的物理坐标成功锁定目标值检索流程提前终止。2. 小值右侧收敛分支else if (matrix[row][col] target)执行left mid 1。数学证明由于虚拟一维序列严格单调递增当前坐标的数值matrix[row][col]小于目标值target意味着在虚拟一维序列中从当前mid索引及其左侧的所有元素0到mid必然都严格小于目标值。结论目标值绝对不可能存在于当前中点及左侧的虚拟区间内该区间被完全物理排除更新左边界指针。3. 大值左侧收敛分支else即 matrix[row][col] target执行right mid - 1。数学证明同理当前坐标的数值大于目标值target意味着在虚拟一维序列中从当前mid索引及其右侧的所有元素mid到m * n - 1必然都严格大于目标值。结论目标值绝对不可能存在于当前中点及右侧的虚拟区间内该区间被完全物理排除更新右边界指针。四、 算法执行状态机步进示例以输入矩阵matrix [[1, 3, 5, 7], [10, 11, 16, 20], [23, 30, 34, 60]]目标值target 3为例规模 3 x 4总元素数 12列数 n 4指针状态机的演进过程如下表所示步骤当前虚拟指针区间 [left, right]计算所得中点 mid映射对应的物理坐标 (row, col)当前物理单元格数值状态判定条件执行的收敛与剪枝动作初始[0, 11]5(5/4, 5%4) - (1, 1)1111 3满足大值分支右边界收缩right 5 - 1 41[0, 4]2(2/4, 2%4) - (0, 2)55 3满足大值分支右边界收缩right 2 - 1 12[0, 1]0(0/4, 0%4) - (0, 0)11 3满足小值分支左边界推进left 0 1 13[1, 1]1(1/4, 1%4) - (0, 1)33 3满足命中条件触发 return true五、 源码实现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; int n matrix[0].length; // 初始化虚拟一维序列的左边界指针 int left 0; // 初始化虚拟一维序列的右边界指针最大线性索引为总元素数减 1 int right m * n - 1; // 边界控制确保区间未闭合或重合维持二分迭代 while (left right) { // 计算一维中心索引采用防加法溢出结构 int mid left (right - left) / 2; // 核心映射核心将一维中心索引转换映射为矩阵真实的行、列物理坐标 int row mid / n; int col mid % n; // 条件分支 1成功精准命中目标值 if (matrix[row][col] target) { return true; } // 条件分支 2当前映射值小于目标值排除虚拟左半区左指针右移 else if (matrix[row][col] target) { left mid 1; } // 条件分支 3当前映射值大于目标值排除虚拟右半区右指针左移 else { right mid - 1; } } // 若越出 while 区间防护网仍未命中证明目标值不存在于矩阵中 return false; } }六、 复杂度分析1. 时间复杂度O(log(m * n))分析算法将二维网格抽象为长度为 m * n 的一维有序序列并在此虚拟序列上执行标准二分查找。每次 while 循环迭代都包含一次常数阶的坐标变换操作一次除法与一次取模均为 O(1)以及常数阶的大小比对。每一次比对都会将当前待搜索的剩余空间缩减为原先的一半。结论总的比较与迭代步数与元素总量 m * n 的对数值呈严格的正比关系时间复杂度收敛于完美的对数阶 O(log(m * n))。2. 空间复杂度O(1)分析算法在执行全流程中仅在运行时栈内存中开辟了m、n、left、right、mid以及映射出的坐标row、col等基础类型的整型局部变量。结论没有申请任何与输入矩阵规模相关的外部物理存储结构或临时数据空间内存空间消耗恒定为常数阶 O(1)。