240. 搜索二维矩阵 II

image.png

image.png

image.png

思路

由行列有序可以知道这是一个二分的问题,并且不会有空矩阵。最容易想到的思想是一行一行的进行二分,这里可以进行一个剪枝,就是当target落入这个行的范围[row[0],row[-1]]才二分去找否则直接走

实现

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        # 遍历行然后对内二分,剪枝
        m = len(matrix)
        n = len(matrix[0])
        # 如何二分?对于某一行 只有在tar落在[matrix[i][0],matrix[i][-1]] 之间才可以二分 对这个区间使用普通二分
        def bisearch(row,target): # 定义一个普通二分
            lc,rc=0,n-1 # 双闭
            while(lc<=rc):
                mid = lc+(rc-lc)//2
                if row[mid]==target:
                    return mid
                if row[mid]<target:
                    lc= mid+1
                elif row[mid]>target:
                    rc=mid-1
            return -1
        
        # 对行数进行二分
        for i in range(m):
            if target>=matrix[i][0] and target<=matrix[i][-1]:
                res=bisearch(matrix[i],target)
                if res>=0:
                    return True
        return False

反思

这种解法显然没有利用到行递增的条件,肯定不是最优解,可以优化的地方比如我们不按行去一行一行的二分,而是使用对角线进行二分,如果比对角线上的元素大,我们去搜对角线所在的行或者列的右或者下部分,这样每次搜索的子问题大小实际上是比上面那种小的,时间复杂度为O((lg(n!))

优化

注意矩阵的四个端点有什么特点 左上角是最小值 有下角是最大值 右上角就非常特殊了,如果我们从右上角出发,向左走值比它小,向右值比它大,到一个新位置我们可以看做是原矩阵减去一行或者一列得到的新矩阵的右上角,例如:从原右上往下一步,相当于把原矩阵剪掉第一行得到的新矩阵的右上角。这样每次要么剪掉一行要么剪掉一列 O(m+n)就能完成搜索。

实现

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        m = len(matrix)
        n = len(matrix[0])
        r = 0
        c = n-1
        while(r<m and c>=0):
            if target == matrix[r][c]:
                return True
            elif target < matrix[r][c]:
                c -= 1
            elif target > matrix[r][c]:
                r += 1
        return False

再解

分治, 通过对原矩阵进行分割递归得到 属于分治法 沿着行的中线去查找第一个 使得matrix[row-1][mid]<target<matrix[row][mid] 的row值 如果找到相等的直接就返回了 有俩种特殊情况 第一个值就大于target和直到最后一个值都小于target,也可以归于一并处理

实现

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        def find_target(matrix,up,down,left,right):   
        # 通过对原矩阵进行分割递归得到 属于分治法 沿着行的中线去查找第一个 使得matrix[row-1][mid]<target<matrix[row][mid] 的row值 如果找到相等的直接就返回了 有俩种特殊情况 第一个值就大于target和直到最后一个值都小于target,也可以归于一并处理
            # 处理基本情况
            if left>right or up>down:
                return False
            if target<matrix[up][left] or target>matrix[down][right]:
                return False

            # 找第一个使得matrix[row-1][mid]<target<matrix[row][mid]的row
            mid = left+(right-left)//2
            c_row = up
            for i in range(up,down+1): # 搜索up-down空间
                if target == matrix[i][mid]:
                    return True
                elif target>matrix[i][mid]:
                    c_row = i+1
            # 按row进行一个分割
            return find_target(matrix,up,c_row-1,mid+1,right) or find_target(matrix,c_row,down,left,mid)

        m = len(matrix)
        n = len(matrix[0])
        return find_target(matrix,0,m-1,0,n-1)
      
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性: 每行...
    放下梧菲阅读 1,301评论 0 0
  • 搜索二维矩阵II 题目 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该...
    饮酒醉回忆阅读 2,967评论 0 1
  • 题目链接难度:中等 类型: 数组 编写一个高效的算法来搜索 m x n 矩阵 matrix 中...
    wzNote阅读 4,572评论 0 3
  • 题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特...
    youzhihua阅读 1,076评论 0 0
  • 推荐指数: 6.0 书籍主旨关键词:特权、焦点、注意力、语言联想、情景联想 观点: 1.统计学现在叫数据分析,社会...
    Jenaral阅读 11,037评论 0 5

友情链接更多精彩内容