【Hot 100】74. 搜索二维矩阵

请添加图片描述

  • 🙋‍♂️ 作者:海码007
  • 📜 专栏:算法专栏
  • 💥 标题:【Hot 100】74. 搜索二维矩阵
  • ❣️ 寄语:书到用时方恨少,事非经过不知难!

引言

这一题刚好还使用到了上一个二分搜索题目的技巧,就是二分法结束后,left左边界指向的是第一个大于等于目标值元素的索引。

搜索二维矩阵

  • 🎈 题目链接:
  • 🎈 做题状态:

我的解题

首先用二分法遍历矩阵第一列数据确定所在行,然后再遍历目标行确定所在列。

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        // 首先用二分法确定所在行,然后再确定所在列
        int rows = matrix.size();
        int cols = matrix[0].size();

        int left = 0;            // 左边界
        int right = rows - 1;    // 右边界

        // 遍历第一列找到目标行,需要找到第一个大于或等于 target 的行
        while (left <= right)
        {
            int mid = (right - left) / 2 + left;
            if (matrix[mid][0] > target)
            {
                // 大于目标值,移动右边界
                right = mid - 1;
            } else if (matrix[mid][0] < target)
            {
                // 小于目标值,移动左边界
                left = mid + 1;
            }
            else
            {
                // 等于目标值
                return true;
            }
        }

        // left-1 就是目标行,left指向第一个大于目标值的位置
        int targetRow = left - 1;
        if (targetRow < 0) return false;    // 要注意这个边界情况,可能会越界!!
        left = 0;
        right = cols - 1;
        while(left <= right)
        {
            int mid = (right - left) / 2 + left;
            if (matrix[targetRow][mid] > target)
            {
                // 大于目标值,移动右边界
                right = mid - 1;
            } else if (matrix[targetRow][mid] < target)
            {
                // 小于目标值,移动左边界
                left = mid + 1;
            }
            else
            {
                // 等于目标值
                return true;
            }
        }

        return false;
    }
};

代码优化

思路清晰:

  1. 先在矩阵的首列中用二分查找确定「目标可能在哪一行」;
  2. 然后在这一行中用二分查找找「目标是否存在」。

这正是这道题目最经典的“两阶段二分法”解法,性能是 O(log m + log n)


✅ 优点总结:

表现
思路清晰两段二分逻辑拆得很干净
边界判断严谨能判断 targetRow < 0 防止越界
变量命名明确逻辑自洽,可读性强
能通过所有测试完全符合 LeetCode 要求

✅ 但还有一些可以轻度优化或提升可读性的地方:


🔧 优化建议 1:二分第一列可以换思路(不找第一个 ≥ target,而是找最后一个 ≤ target)

你现在的代码是:

while (left <= right) {
    ...
}
// left - 1 就是目标行
int targetRow = left - 1;

这段虽然正确,但可以写得更直观一些,比如直接写成找 最后一个 ≤ target 的行,让语义更明确。

不过保留你原写法也没问题,因为你注释写得清楚,不影响理解。


🔧 优化建议 2:二段式二分可合并为一段式

还有一种更极致优化(不一定需要改)的做法是——把整个二维矩阵当成一维数组处理,只做一次二分查找:

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        // 首先用二分法确定所在行,然后再确定所在列
        int rows = matrix.size();
        int cols = matrix[0].size();

        int left = 0;                   // 左边界
        int right = rows * cols - 1;    // 右边界

        // 遍历第一列找到目标行,需要找到第一个大于或等于 target 的行
        while (left <= right)
        {
            int mid = (right - left) / 2 + left;
            if (matrix[mid / cols][mid % cols] > target)		// 坐标映射是关键点,一个是除以,一个是取余数。
            {
                // 大于目标值,移动右边界
                right = mid - 1;
            } else if (matrix[mid / cols][mid % cols] < target)
            {
                // 小于目标值,移动左边界
                left = mid + 1;
            }
            else
            {
                // 等于目标值
                return true;
            }
        }
        
        return false;
    }
};
✅ 优点:
  • 一次二分,代码更短;
  • 时间复杂度仍为 O(log(m*n)),更紧凑。
⚠️ 缺点:
  • 可读性略差一点,不如你那种“先找行再找列”直观;
  • 对初学者不够友好。

📌 总结评价:

方面你的写法优化建议
正确性✅ 完美✅ 一样正确
可读性✅ 强(注释清晰)⬆️ 可略简化
性能✅ O(log m + log n)✅ 可合并为 O(log mn)
工程推荐✅ 很推荐✅ 合并写法适合追求极简的情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值