【Hot 100 刷题计划】 LeetCode 74. 搜索二维矩阵 | C++ 二分查找 (一维展开法)

LeetCode 74. 搜索二维矩阵

📌 题目描述

题目级别:中等

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

  • 每行中的整数从左到右按非严格递增顺序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false

  • 示例 1:
    输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
    输出:true

💡 破题思路:降维打击,化二维为一维

这道题虽然披着"二维矩阵"的外衣,但由于它满足**"全局严格递增"(不仅行内递增,且下一行开头大于上一行结尾),我们可以直接对它实施降维打击**。

如果我们将这个 mn 列的矩阵像拉面条一样拉直,它就是一个长度为 m * n 的严格单调递增的一维数组。既然是一维有序数组,那寻找目标值最快的方法毫无疑问就是二分查找

本题核心:坐标映射魔法

在虚拟的一维数组中,我们二分出的中间索引是 mid。那么这个 mid 对应回真实的二维矩阵,它的行号和列号是多少呢?

假设矩阵有 n 列(每行有 n 个元素):

  • 行号mid / n (前面有几个完整的行)
  • 列号mid % n (在当前行里排第几个)

我们不需要真的去开辟一个一维数组把数据拷出来,只需要在脑海中虚拟出这个一维数组,并在访问矩阵元素时套用这个公式即可!


💻 C++ 代码实现 (左闭右开二分模板)

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size(), n = matrix[0].size();
        
        // 使用左闭右开区间 [0, m * n)
        int l = 0, r = m * n;

        while (l < r)
        {
            int mid = l + (r - l) / 2; // 防止溢出的标准写法 (原写法 (l+r)/2 逻辑上亦正确)
            
            // 核心数学映射:一维索引转换为二维坐标
            int mid_val = matrix[mid / n][mid % n];

            if (mid_val == target) {
                return true;
            }
            else if (mid_val < target) {
                l = mid + 1; // 目标在右半边
            }
            else {
                r = mid;     // 目标在左半边,由于是右开区间,r 直接等于 mid
            }
        }

        return false;
    }
};
相关推荐
8Qi828 分钟前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
搬砖魁首2 小时前
基础能力系列 - 多线程2 - 条件变量
c++·rust·条件变量·原子类型·线程同步互斥
chase_my_dream2 小时前
C++ + SLAM 高频面试问题整理
开发语言·c++·面试
牛油果子哥q2 小时前
【C++ STL string 】C++ STL string 终极精讲:底层原理、内存机制、全套API、深浅拷贝、易错坑点与工程实战规范
数据库·c++
dingzd953 小时前
跨境社媒运营越到后面 越比拼账号的表达稳定性
大数据·人工智能·矩阵·内容营销
凡人叶枫4 小时前
Effective C++ 条款04:确定对象被使用前已先被初始化
java·linux·开发语言·c++·嵌入式开发
不想写代码的星星4 小时前
std::move 根本不移动,就像老婆饼里没有老婆
c++
redaijufeng4 小时前
C++雾中风景7:闭包
c++·算法·风景
小欣加油5 小时前
leetcode287寻找重复数
数据结构·c++·算法·leetcode
思麟呀5 小时前
C++11 核心特性(三):强类型枚举、static_assert 与 std::tuple
开发语言·c++