Hot 100 --- 搜索二维矩阵

本文概览:本文讲解搜索二维矩阵的核心思路:利用矩阵完全递增的性质,通过两次二分查找快速定位目标值


一、题目


二、题目分析

这题的矩阵有一个关键性质:完全递增

  • 每行从左到右递增
  • 下一行所有的数都比上一行大
  • 按照"一行一行从左到右"的顺序遍历,所有数字是递增的

比如这个矩阵:

复制代码
 1   3   5   7
10  11  16  20
23  30  34  60

展开后就是 [1, 3, 5, 7, 10, 11, 16, 20, 23, 30, 34, 60],完全递增。

基于这个性质,我们可以采取两次二分查找的方法快速找到目标值:

  1. 第一次二分:确定 target 在哪一行
  2. 第二次二分:在确定的行内查找 target

思路概览

Java 实现代码如下

java 复制代码
public boolean searchMatrix(int[][] matrix, int target) {
    int height = matrix.length;
    int width = matrix[0].length;

    int row;
    int bottom = 0;
    int top = height - 1;
    while(bottom <= top) {
        int mid = bottom + (top - bottom) / 2;
        // 目标在当前行
        if(matrix[mid][0] <= target && matrix[mid][width - 1] >= target) {
            row = mid;
            // 目标在当前行, 二分查找
            int left = 0;
            int right = width - 1;
            while(left <= right) {
                int col = left + (right - left) / 2;
                if(matrix[row][col] == target) {
                    return true;
                } else if(matrix[row][col] > target) {
                    right = col - 1;
                } else {
                    left = col + 1;
                }
            }
            return false;
        }
        // 目标在当前行之前
        else if(matrix[mid][0] > target) {
            top = mid - 1;
        }
        // 目标在当前行之后
        else if(matrix[mid][width - 1] < target) {
            bottom = mid + 1;
        }
    }
    return false;
}

思路简要说明:

  1. 第一次二分 :对行进行二分,判断 target 是否在当前行的范围内(>= 第一个元素<= 最后一个元素
  2. 第二次二分:在确定的行内,用标准的二分查找找 target
  3. 时间复杂度:O(log m + log n),m 是行数,n 是列数

三、思路详解

第一步:矩阵的关键性质

矩阵的关键性质是完全递增。这意味着:

  • 每行的第一个元素是这一行的最小值
  • 每行的最后一个元素是这一行的最大值
  • 第 i 行的所有元素都小于第 i+1 行的所有元素

所以我们可以用每行的首尾元素来判断 target 是否在这一行:

复制代码
matrix[mid][0] <= target && matrix[mid][width-1] >= target
第二步:第一次二分------确定行

对行进行二分查找,每次取中间行 mid,判断 target 是否在这一行的范围内:

  • matrix[mid][0] <= target && matrix[mid][width-1] >= target:target 在这一行,进入第二次二分
  • matrix[mid][0] > target :target 在这一行之前(上面的行),更新 top = mid - 1
  • matrix[mid][width-1] < target :target 在这一行之后(下面的行),更新 bottom = mid + 1
第三步:第二次二分------确定列

确定了行 row 之后,在这一行内用标准的二分查找找 target:

  • left = 0right = width - 1
  • mid = left + (right - left) / 2
  • matrix[row][mid] == target:找到,返回 true
  • matrix[row][mid] > target:target 在左边,right = mid - 1
  • matrix[row][mid] < target:target 在右边,left = mid + 1
第四步:完整执行过程

以这个矩阵为例,target = 11

复制代码
 1   3   5   7
10  11  16  20
23  30  34  60

第一次二分:确定行

复制代码
初始:bottom=0, top=2

第 1 轮:
  mid = 0 + (2-0)/2 = 1
  matrix[1][0] = 10, matrix[1][3] = 20
  10 <= 11 && 11 <= 20 → target 在第 1 行 ✓
  进入第二次二分

第二次二分:确定列

复制代码
初始:left=0, right=3

第 1 轮:
  col = 0 + (3-0)/2 = 1
  matrix[1][1] = 11 == 11 → 找到!返回 true ✓

再举一个找不到的例子,target = 13

第一次二分:确定行

复制代码
初始:bottom=0, top=2

第 1 轮:
  mid = 1
  matrix[1][0] = 10, matrix[1][3] = 20
  10 <= 13 && 13 <= 20 → target 在第 1 行 ✓
  进入第二次二分

第二次二分:确定列

复制代码
初始:left=0, right=3

第 1 轮:
  col = 1, matrix[1][1] = 11 < 13
  left = 2

第 2 轮:
  left=2, right=3
  col = 2, matrix[1][2] = 16 > 13
  right = 1

第 3 轮:
  left=2, right=1
  left > right,退出循环
  返回 false
第五步:时间复杂度分析
  • 第一次二分:对行进行二分,时间复杂度 O(log m),m 是行数
  • 第二次二分:对列进行二分,时间复杂度 O(log n),n 是列数
  • 总时间复杂度:O(log m + log n)

如果直接遍历整个矩阵,时间复杂度是 O(m × n)。二分查找的优势非常明显。


四、总结

搜索二维矩阵的核心是利用矩阵完全递增的性质,通过两次二分查找快速定位目标值:

  1. 第一次二分:确定 target 在哪一行(用每行的首尾元素判断范围)
  2. 第二次二分:在确定的行内查找 target

这个思路可以推广到所有"有序矩阵查找"类题目。

相关推荐
旖旎夜光1 小时前
LeetCode 1262:可被三整除的最大和 (贪心算法)—— 题解
数据结构·c++·算法·leetcode·贪心算法
心运软件1 小时前
基于机器学习的智能邮件分类系统:从数据采集到模型部署全流程实战
人工智能·python·算法·随机森林·机器学习·分类·scikit-learn
CoderYanger1 小时前
Java EE:9.JVM(课件内容-上篇)
java·jvm·程序人生·面试·职场和发展·java-ee·程序员创富
xiaoqiMikko1 小时前
Spring Cloud Config 这个 CVE 的补丁,Maven Central 上根本没有
java·spring boot
残月心殇 请珍惜枸1 小时前
.NET陷阱之五:奇怪的OutOfMemoryException——大对象堆引起的问题与对策
java·jvm·.net
用户3126874877201 小时前
Spring Boot 配置体系到底怎么加载的?从 application.yml 到 @Conditional 的全链路拆解
java·spring boot
Bonnie_12151 小时前
08-JUC并发基础-AQS-补充共享锁
java·开发语言
Zane19941 小时前
线程池入门:7 大核心参数与 4 种拒绝策略
java·后端
Zldaisy3d2 小时前
连续纤维增材制造的机翼已飞上天,复材打印在低空飞行器上还需翻过几道坎?
java·前端·数据库