leetcode_74 搜索二维矩阵

1. 题意

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

  • 每行中的整数从左到右按非严格递增顺序排列。

  • 每行的第一个整数大于前一行的最后一个整数。

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

否则,返回 false 。

2. 题解

2.1 暴力

逐个判断即可;

时间复杂度 O ( m n ) O(mn) O(mn)

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        
        for (auto &M: matrix) {
            for (auto v: M) {
                if( v == target)
                    return true;
            }
        }
        return false;
    }
};
2.2 逐行二分

由于一行的数是有序的,因此可以不用完全遍历。

而且二分查找target

时间复杂度 O ( m log ⁡ n ) O(m \log n) O(mlogn)

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (0 == m)
            return false;
        
        for (int i = 0;i < m; ++i) {
            auto it = lower_bound( matrix[i].begin(), matrix[i].end(), target);
            if ( it != matrix[i].end() && *it == target)
                return true;
        }

        return false;
    }
};
2.3 整体二分

由于 r r r行的最后一个元素是小于 r + 1 r+1 r+1行的第一个元素。

我们可以将这个二维数组给看成一个有序的一维数组。

用下标 k k k表示原来数组 m a t r i x [ k / n ] [ k % n ] matrix[k/n][k \%n] matrix[k/n][k%n]这个元素,

在 [ 0 , m n ) [0,mn) [0,mn)这个新下标间进行二分。

时间复杂度 O ( log ⁡ m n ) = O ( log ⁡ m + log ⁡ n ) O(\log mn) = O(\log m + \log n) O(logmn)=O(logm+logn)

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (0 == m)
            return false;
        int n = matrix[0].size();

        int l = 0;
        int r = m * n - 1;


        while ( l <= r) {
            int mid = ((r - l) >> 1) + l;

            int v = matrix[mid / n][mid % n];

            if ( v == target)
                return true;
            if ( v > target)
                r = mid - 1;
            else 
                l = mid + 1;
        }



        return false;
    }
};
2.4 两次二分

我们可以二分查找最后一列,找到第一个不小于 t a r g e t target target所在的行。

在对行进行二分,查找最终的 t a r g e t target target值。

时间复杂度 O ( log ⁡ m + log ⁡ n ) O(\log m + \log n) O(logm+logn)

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (0 == m)
            return false;
        int n = matrix[0].size();

        
        int l;
        int r;

        l = 0;
        r = m;
        // log m
        while ( l < r) {
            int mid = ((r - l) >> 1) + l;

            int v = matrix[mid][n - 1];
            if ( v == target)
                return true;
            
            if ( v > target)
                r = mid;
            else
                l = mid + 1;
        }

        if ( r >= m )
            return false;

        int rows = r;

        //cout << rows << endl;
        l = 0;
        r = n;

        while ( l < r) {
            int mid = ((r - l) >> 1) + l;

            //cout << mid << ": " << matrix[rows][mid] << endl;

            int v = matrix[rows][mid];
            if ( v == target)
                return true;

            if ( v < target)
                l = mid + 1;
            else 
                r = mid;
        }

        return false;
    }
};
2.5 二叉搜索树

这个想法来自三叶姐,宫水三叶。

把这样的二维数组想看成以右上角为根节点的二叉搜索树。

当前节点的左边节点必然小于当前节点,

当前节点的下边节点必然大于当前节点。

我们从根开始,如果当前节点大于target,就向左走;

如果当前节点小于target,就向下走。

重复上面的过程,直到超过边界或者找到target

时间复杂度 O ( m + n ) O(m+n) O(m+n)

cpp 复制代码
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (0 == m)
            return false;
        int n = matrix[0].size();

        int x = 0;
        int y = n - 1;

        while (x < m && y >= 0) {
            int v = matrix[x][y];

            if (v == target)
                return true;
            
            if ( v > target)
                y--;
            else 
                x++;
        }
        

        return false;
    }
};

参考

三叶
leetcode

相关推荐
hansang_IR6 小时前
【题解 | 两种做法】洛谷 P4208 [JSOI2008] 最小生成树计数 [矩阵树/枚举]
c++·算法·dfs·题解·枚举·最小生成树·矩阵树定理
补三补四7 小时前
贝叶斯向量自回归模型 (BVAR)
android·算法·数据挖掘·数据分析·回归
幂简集成explinks7 小时前
GPT-Realtime 弹幕TTS API:低延迟秒开集成实战
人工智能·后端·算法
一只鱼^_8 小时前
365. 水壶问题(详解)
java·javascript·c++·leetcode·线性回归
午彦琳8 小时前
力扣404 代码随想录Day15 第三题
算法·leetcode·职场和发展
Dream it possible!8 小时前
LeetCode 面试经典 150_滑动窗口_串联所有单词的子串(32_30_C++_困难)(滑动窗口:控制起点和滑动距离)
c++·leetcode·面试·滑动窗口
Q741_1478 小时前
C++ 面试高频考点 力扣 35. 搜索插入位置 二分查找 左右端点查找 题解 每日一题
c++·算法·leetcode·面试·二分查找
saddhu.8 小时前
C++ 快速复习指南(上半部分)
java·c++·算法
执子手 吹散苍茫茫烟波9 小时前
leetcode46.全排列
java·leetcode·链表·深度优先·回溯法