lc240. 搜索二维矩阵 II(C++|二分|思维|面试)

力扣

题目描述

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
 

示例 1:


输入: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]], target = 5
输出:true
示例 2:


输入: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]], target = 20
输出:false 

提示:

m == matrix.length
n == matrix[i].length
1 <= n, m <= 300
-109 <= matrix[i][j] <= 109
每行的所有元素从左到右升序排列
每列的所有元素从上到下升序排列
-109 <= target <= 109

果果念

这道题目是一道面试真题,在lc上看到的。我是第一次做,二分法是很容易想到的。在lc平台上,复杂度为O(mlogn),只超过了10%左右的C++提交者。可以仔细分析一下,二分法只利用了一个性质 ,就是看你按照行进行二分穷举各列,还是按照列进行二分穷举各行了,反正总体来说,没有同时顾及行列有序的性质,因此有更优化的方法。

“Z字型”扫描法,暂且这样叫它吧。这各方法的巧妙之处在于如果我们在矩阵的右上方遍历,一直到左下方,那么按行来说,数值越来越小,按列来说,数值越来越大。现在可以明白了吧,因为如果常规从坐上遍历的话,往下、往右都是递增的。但是左下方遍历就不一样,如果当前值小于target,那么row++;如果当前值大于target,那么col--;最后注意一下边界条件即可,真的好巧妙啊!让我们来计算一下这个的复杂度,O(m+n),天哪,太棒了吧~

//二分法
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        //二分查找 中间的一行中间值
        for(int i=0;i<matrix.size();i++){
            if(binarySearch(matrix,i,0,matrix[i].size()-1,target)==true){
                return true;
            }
        }
        return false;
    }
    bool binarySearch(vector<vector<int>>& matrix,int row,int left,int right,int target){
        if(right<left) return false;
        int mid=(left+right)/2;
        if(matrix[row][mid]==target){
            return true;
        }else if(matrix[row][mid]<target){
            return binarySearch(matrix,row,mid+1,right,target);
        }else{
            //matrix[row][mid]>target
            return binarySearch(matrix,row,left,mid-1,target);
        }
    }
};

//Z字形查找
class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) {
        //Z字形查找
        int m=matrix.size(),n=matrix[0].size();
        int row=0,col=n-1;
        while(row<m&&col>=0){
            if(matrix[row][col]==target){
                return true;
            }else if(matrix[row][col]<target){
                row++;
            }else {//matrix[row][col]>target
                col--;
            }
        }
        return false;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值