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;
    }
}
相关推荐
XH华1 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生2 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_2 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子2 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
菜鸡中的奋斗鸡→挣扎鸡2 小时前
滑动窗口 + 算法复习
数据结构·算法
Lenyiin2 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码3 小时前
Cmd命令大全(万字详细版)
python·算法·小程序
scan7243 小时前
LILAC采样算法
人工智能·算法·机器学习
菌菌的快乐生活3 小时前
理解支持向量机
算法·机器学习·支持向量机
大山同学3 小时前
第三章线性判别函数(二)
线性代数·算法·机器学习