Leetcode 240. Search a 2D Matrix II

Leetcode 240. Search a 2D Matrix II

题目

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted in ascending from left to right.
  • Integers in each column are sorted in ascending from top to bottom.

Example:

Consider the following matrix:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

Given target = 5, return true.

Given target = 20, return false.

解题思路

注意到矩阵左下角或右上角元素的特殊性,以左下角为例:若左下角元素的值大于目标值,则最下一行的元素的值都大于目标值;若左下角元素的值小于目标值,则最左一行的元素的值都小于目标值。因此,将左下角的值于目标值做比较,都可以排除最下面一行或最左边一列。接着在去除一行或一列后的矩阵的基础上再次将目标值与新的左下角的值进行比较,重复上述步骤,即可确定答案。左下角的变化对原矩阵来说,是一条从原矩阵左下角开始,向上或向右前进的折线,最坏的情况是从原矩阵左下角前进到右上角,需要m+n步,时间复杂度为O(m+n)。

代码如下:

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (m == 0) return false;
        int n = matrix[0].size();
        int i = m-1;
        int j = 0;
        while( i >=0 && j < n){
            if (matrix[i][j] < target){
                j++;
            }
            else if (matrix[i][j] > target) {
                i--;
            }
            else return true;
        }
        return false;   
    }
};

方法二:四分法

矩阵中间的元素可以将矩阵分为4份。若中间元素值比目标值小,则左上角的矩阵的值均小于目标值,而与目标值相等的元素可以出现在其他3个矩阵中;若中间元素值比目标值大,则右下角的矩阵的值均大于目标值,而与目标值相等的元素可以出现在其他3个矩阵中。

n x n 矩阵来分析,时间复杂度有如下递推式: T(n)=3T(n/2)+O(1) T ( n ) = 3 T ( n / 2 ) + O ( 1 )

因此,时间复杂度 T(n)=O(nlong23)=O(n1.58) T ( n ) = O ( n l o n g 2 3 ) = O ( n 1.58 )

代码如下:

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (m == 0) return false;
        int n = matrix[0].size();
        return helper(matrix,0,m-1,0,n-1,target);
    }

private:
    bool helper(vector<vector<int>>& matrix, int rowStart, int rowEnd, int colStart, int colEnd, int target ){
        if(rowStart>rowEnd||colStart>colEnd){
            return false;
        }
        int rm=(rowStart+rowEnd)/2, cm=(colStart+colEnd)/2;
        if(matrix[rm][cm]== target){
            return true;
        }
        else if(matrix[rm][cm] >target){
            return helper(matrix, rowStart, rm-1,colStart, cm-1,target)||
            helper(matrix,  rm, rowEnd, colStart,cm-1,target) ||
            helper(matrix, rowStart, rm-1,cm, colEnd,target);
        }
        else{
            return helper(matrix, rm+1, rowEnd, cm+1,colEnd,target)||
            helper(matrix,  rm+1, rowEnd, colStart,cm,target) ||
            helper(matrix, rowStart, rm,cm+1, colEnd,target);
        }
    }
};

方法三:二分法

先在矩阵中间行找到第一个大于或等于目标值的元素,若该元素值等于目标值,则返回true;否则,目标值只能出现在该元素正上方的矩阵中或该元素左边元素正下方的矩阵中。而在一行中找到第一个大于或等于目标值的元素可以采用二分法。

因此,以 n x n 矩阵来分析,时间复杂度为:

T(n)=2T(n/2)+clog2n T ( n ) = 2 T ( n / 2 ) + c ∗ l o g 2 n
=2log2nT(1)+clog2n1k=0(2klog2(n/2k)) = 2 l o g 2 n T ( 1 ) + c ∑ k = 0 l o g 2 n − 1 ( 2 k l o g 2 ( n / 2 k ) )
=O(n)+c(2nlog2n2) = O ( n ) + c ( 2 n − l o g 2 n − 2 )
=O(n) = O ( n )

代码如下:

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        int m = matrix.size();
        if (m == 0) return false;
        int n = matrix[0].size();
        return binPart(matrix, target, 0, 0, m-1, n-1);
    }

private:
    bool binPart(vector<vector<int>>& matrix, int target, int x1, int y1, int x2, int y2) {
        if (x1>x2 || y1>y2) return false;
        if (target < matrix[x1][y1] || target > matrix[x2][y2]) {
            return false;
        }
        int l = y1;
        int r = y2;
        int midx = (x1+x2)/2;
        while(l < r) {
            int midy = (l+r)/2;
            if (matrix[midx][midy] < target) {
                l = midy + 1;
            }
            else {
                r = midy;
            }
        }
        if (matrix[midx][l] == target) return true;
        if (matrix[midx][l] < target) l++;
        return binPart(matrix, target, x1, l, midx-1, y2) ||
               binPart(matrix, target, midx+1, y1, x2, l-1);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值