LeetCode刷题记录----240.搜索二维矩阵Ⅱ(medium)

2025/7/17

题目(medium):


我的思路:

已经知道行列都是按从小到大的顺序排列好的,而我们知道二分查找很适合用于这种已经排好序的数组中进行查找操作。所以考虑以对角线上的位置为起点,以行列的最右边、最下边为终点,在遍历对角线的过程中,对行列同时进行二分查找的操作

大概是这么个意思

代码如下:

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        #考虑行列同时折半查找,以对角线为起点
        m,n = len(matrix), len(matrix[0])

        for i in range(min(m,n)):    #以行列数最小值为遍历可以达到的最大值防止越界
             #start代表是当前所在对角线位置
            start = i  

            #更新左右上下的边界位置
            up,down = i,m-1
            left,right =i,n-1

            #行进行折半查找
            while left <= right:
                mid = (left + right) //2
                midNum = matrix[start][mid]
                if midNum == target:
                    return True
                elif midNum > target:
                    right = mid-1
                elif midNum < target:
                    left = mid+1
            #列进行折半查找
            while up <= down:
                mid = (up + down) // 2
                midNum = matrix[mid][start]
                if midNum == target:
                    return True
                elif midNum > target:
                    down = mid-1
                elif midNum < target:
                    up = mid + 1            

        return False    #查到末尾了还没查到那就是没有了

时间复杂度:O(min(m,n)*(log2n + log2m)        【感觉好像也不低哇】

空间复杂度:O(1)


优化思路:

造成时间复杂度过大的原因主要是,目标值越接近右下角,那遍历搜索的时间就越接近于逐行都二分查找一遍,尤其是在数组越来越大的时候,就更加没有优势了。

那可不可以考虑,先通过二分查找确定元素大致会处于哪一行,然后再在这行中进行二分查找呢?如果可以这样的话那时间复杂度就可以优化到O(log2m + log2n)

 但是实际上要定位到哪一行似乎比较困难,因为从头开始看的话,任意一行开头数字大于target的都有后面可能存在target;那从结尾看的话,任意一行结尾数字小于target的前面都有可能存在target。

所以只能说排除一定不存在target的行,但是还是不能够定位到target具体在哪一行,所以这个思路是没有办法实现的


更好地思路:

那上面优化的时候想到了,从结尾开始比对的话,要是比target小,那肯定可以排除不在这一行。要是比target大,那就前面还有可能存在target。

也就是说,从右上角(0,n-1)的位置开始搜索,如果当前(x,y)位置的值>target,那就y--;如果当前(x,y)位置的值<target,那就x++。这样进行Z字形搜索即可

终止条件就是当(x,y)掉出索引范围的时候,那就说明target不在这里面

代码如下:

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        #考虑从右上角开始搜索
        m,n = len(matrix),len(matrix[0])
        x,y = 0,n-1     #x,y从右上角开始搜索
        
        #有相等,大于,小于三种情况
        while(x < m and y >= 0):
            curNum = matrix[x][y]
            if curNum == target:    #相等直接返回
                return True
            elif curNum > target:   #当前值比目标值还大,目标值可能在这行前面
                y -= 1
            elif curNum < target:   #当前值比目标值还小,说明这行不可能存在目标值,所以进入下一行
                x += 1

        return False

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

空间复杂度:O(1)

太优雅了


总结:

①对排好序的数组中查找,很快就能反应过来是二分查找

②对于这种有很大很多块的有序的矩阵,考虑排除法,优先选择排除一定没有的部分,而不是优先考虑可能有的部分可以更好地优化思路

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萘柰奈

谢谢老板喵

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值