leetcode之hot100---240搜索二维矩阵II(C++)

思路一:通过遍历主对角线上元素判断查找方向

  • 主对角线遍历

    • 遍历主对角线上的每个元素(matrix[i][i]),其中 i 的范围是 [0, min(m, n) - 1]
    • 如果目标值小于当前主对角线元素,说明目标值可能在当前元素的左上区域(即当前行的左侧或当前列的上方)。
    • 如果目标值大于主对角线上的所有元素,则需要在剩余的行和列中继续查找。
  • 二分查找辅助函数

    • binarySearchRow:在给定的行范围 [0, colLimit-1] 上进行二分查找。
    • binarySearchCol:在给定的列范围 [0, rowLimit-1] 上进行二分查找。
  • 查找策略

    • 每次遍历主对角线元素时,通过二分查找缩小范围,分别查找目标值是否在当前行或当前列中。
cpp 复制代码
#include <vector>
#include <algorithm> // for std::lower_bound
using namespace std;

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        int n = matrix[0].size();
        int len = min(m, n); // 主对角线的长度

        for (int i = 0; i < len; ++i) {
            // 如果主对角线上的元素等于目标值,直接返回 true
            if (matrix[i][i] == target) {
                return true;
            }

            // 如果目标值小于主对角线上的元素,目标可能在当前行的左侧或当前列的上方
            if (matrix[i][i] > target) {
                // 在第 i 行的左侧 [0, i-1] 范围内查找
                if (binarySearchRow(matrix, target, i)) {
                    return true;
                }
                // 在第 i 列的上方 [0, i-1] 范围内查找
                if (binarySearchCol(matrix, target, i)) {
                    return true;
                }
                // 如果在当前行和列都没有找到,直接返回 false
                return false;
            }
        }

        // 如果目标值大于主对角线上的所有元素,则在剩余行和列中查找
        return false;
    }

private:
    // 在第 rowIndex 行的 [0, colLimit-1] 范围内进行查找
    bool binarySearchRow(const vector<vector<int>>& matrix, int target, int rowLimit) {
        auto it = lower_bound(matrix[rowLimit].begin(), matrix[rowLimit].begin() + rowLimit, target);
        return it != matrix[rowLimit].begin() + rowLimit && *it == target;
    }

    // 在第 colIndex 列的 [0, rowLimit-1] 范围内进行查找
    bool binarySearchCol(const vector<vector<int>>& matrix, int target, int colLimit) {
        vector<int> column;
        for (int i = 0; i < colLimit; ++i) {
            column.push_back(matrix[i][colLimit]);
        }
        auto it = lower_bound(column.begin(), column.end(), target);
        return it != column.end() && *it == target;
    }
};
  • 时间复杂度O((min(m, n))²)
  • 空间复杂度O(min(m, n))

思路二:暴力解法

遍历矩阵,查找成功返回true,否则返回false

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        int n = matrix[0].size();
        //矩阵为空查找失败
        if(n == 0){
            return false;
        }
        //目标越界查找失败
        if(target < matrix[0][0] || target > matrix[m - 1][n - 1]){
            return false;
        }
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(matrix[i][j] == target){
                    return true;
                }
            }
        }
        //遍历整个矩阵没找到目标值,查找失败
        return false;
    }
};
  • 时间复杂度:O(m * n)
  • 空间复杂度:O(1)

思路三:二分查找

由于矩阵内部数字是升序的,在每一行中进行二分查找,查找成功返回true,否则返回false

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        //遍历矩阵中第一列的所有元素
        for(auto &row: matrix){
            //在每一行中进行二分查找
            auto it = lower_bound(row.begin(), row.end(), target);
            //查找成功返回true
            if(it != row.end() && *it == target){
                return true;
            }
        }
        //查找不成功返回false
        return false;
    }
};
  • 时间复杂度:O(nlogn),注:二分查找算法的时间复杂度为O(logn)
  • 空间复杂度:O(1)

获取迭代器值的四种方法:

  1. 使用解引用运算符 *

    cpp 复制代码
    vector<int> vec = {1, 3, 5, 7, 9};
    auto it = lower_bound(vec.begin(), vec.end(), 3);
    int value = *it;  // 直接获取值
  2. 获取下标位置(仅适用于连续容器如vector)

    cpp 复制代码
    vector<int> vec = {1, 3, 5, 7, 9};
    auto it = lower_bound(vec.begin(), vec.end(), 3);
    int index = it - vec.begin();  // 获取下标位置
    int value = vec[index];        // 通过下标获取值
  3. 对于pair或结构体类型,使用箭头运算符 ->

    cpp 复制代码
    vector<pair<int, string>> vec = {{1,"a"}, {3,"b"}, {5,"c"}};
    auto it = lower_bound(vec.begin(), vec.end(), make_pair(3, ""));
    int first = it->first;      // 获取pair的first
    string second = it->second; // 获取pair的second
  4. 使用迭代器的distance函数获取位置

    cpp 复制代码
    vector<int> vec = {1, 3, 5, 7, 9};
    auto it = lower_bound(vec.begin(), vec.end(), 3);
    int index = distance(vec.begin(), it);

注意:在使用迭代器之前,应该先检查迭代器是否有效,避免解引用end()迭代器。

思路四:Z字形查找

从右上角向左下角,如果当前遍历到的数字大于目标值,就向左移动,如果当前遍历到的数字小于目标值,就向下移动,遍历到目标值返回true,否则返回false

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        int n = matrix[0].size();
        //(x,y)为矩阵右上角数字的坐标
        int x = 0, y = n - 1;
        //从右上角开始向左下角遍历
        while(x < m && y >= 0){
            //查找成功返回true
            if(matrix[x][y] == target){
                return true;
            }
            // 如果当前值大于目标值,则向左移动一列
            // (因为矩阵的每一行从左到右递增)
            else if(matrix[x][y] > target){
                --y;
            }
            // 如果当前值小于目标值,则向下移动一行
            // (因为矩阵的每一列从上到下递增)
            else{
                ++x;
            }
        }
        // 如果遍历结束仍未找到目标值,返回 false
        return false;
    }
};
  • 时间复杂度:O(m+n)
  • 空间复杂度:O(1)

同时也可以从左下角向右上角进行查找,只需要基于上述代码进行少量修改:

cpp 复制代码
int x = m - 1, y = 0;
//从左下角开始向右上角遍历
while(x >= 0 && y < n){
    //查找成功返回true
    if(matrix[x][y] == target){
       return true;
    }
    // 如果当前值大于目标值,则向上移动一列
    // (因为矩阵的每一行从上到下递增)
    else if(matrix[x][y] > target){
        --x;
    }
    // 如果当前值小于目标值,则向右移动一行
    // (因为矩阵的每一列左到右递增)
    else{
        ++y;
    }
}
相关推荐
那年窗外下的雪.16 分钟前
AIDC 学习日志|第 22 天|All-Active/Single-Active 故障演练设计
服务器·网络·学习·算法·哈希算法
wzdark1 小时前
基于启发式搜索的最优路径规划算法研究4
算法
动词ing1 小时前
【学习笔记】数据结构栈与队列(栈先进后出+队列先进先出+括号匹配+消消乐模型)
数据结构·笔记·学习
l1t1 小时前
用superpi、tinypi、tpi等工具计算圆周率的比较
c语言·算法
a187927218311 小时前
【算法】链表(二):链表上的双指针——变速、异链与定距,和一份路程账本
数据结构·算法·leetcode·链表·go·指针·环形链表
2601_958352902 小时前
还要写 AEC 算法?0 代码 + 6 个引脚,F-18 让通话清晰度提升 300%
人工智能·算法·降噪消回音
happyprince3 小时前
03-regmix-深刻观-哲学与升华
算法
zcmodeltech3 小时前
火电厂模型能演示冷态启动和故障处理吗?——基于STM32与Modbus RTU的集控实训控制系统设计
数据结构·stm32·单片机·嵌入式硬件·能源
一路向阳~负责的男人3 小时前
运动控制算法收录
算法
czt_java3 小时前
5个核心位运算公式
算法