240. 搜索二维矩阵 II
剑指 Offer 04. 二维数组中的查找

题目

在一个 n m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
*示例:

现有矩阵 matrix 如下:

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

给定 target = 5,返回 true
给定 target = 20,返回 false
限制:

0 <= n <= 1000
0 <= m <= 1000

题解

首先的思路是,通过 [left,right]x[low,high] 确定一个搜索区域,先是

  1. 横向搜索,让right停在比target大的一列,然后 low++
  2. 竖向搜索,让high停在比target大的一行,然后 left++

重复1、2环节即可,其实可以通过二分法优化搜索过程,但实际上right和high的移动不太频繁,使用二分法速度反而比直接循环慢。
QQ图片20210307220656.png

class Solution(object):
    def findNumberIn2DArray(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        n = len(matrix)
        if n == 0:
            return False
        m = len(matrix[0])
        if m == 0:
            return False
        left, low = 0, 0
        high = n-1
        right = m-1
        while left <= right and low <= high:
            for j in range(right, left-1, -1):
                if matrix[low][j] < target:
                    break
                elif matrix[low][j] == target:
                    return True
            right = min(j+1, m-1)
            low += 1
            if low > high:
                break
            for i in range(high, low-1, -1):
                if matrix[i][left] < target:
                    break
                elif matrix[i][left] == target:
                    return True
            high = min(i+1, n-1)
            left += 1
        return False

执行用时:24 ms, 在所有 Python 提交中击败了81.64%的用户 内存消耗:17 MB, 在所有 Python 提交中击败了79.01%的用户

由于 high, right 是单调递减的,因此算法复杂度为 O(m+n)

解法2

从右上角出发:

  1. 一直往左走,停到刚好比target小的一个位置
  2. 然后再往下走一格
  3. 重复第1步

QQ图片20210307223355.jpg
这个复杂度其实和上面的方法一样,都是 O(m+n) ,但理解和实现起来更简单。

class Solution(object):
    def findNumberIn2DArray(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        n = len(matrix)
        if n == 0:
            return False
        m = len(matrix[0])
        if m == 0:
            return False
        i, j = 0, m-1
        while i < n and j >= 0:
            val = matrix[i][j]
            print(val)
            if val > target:
                j -= 1
            elif val == target:
                return True
            else:
                i+=1 
        return False