• 《剑指 Offer》学习记录:题 4:二维数组中的查找


    题 4:二维数组中的查找

    题干

    在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。——《剑指 Offer》P44

    测试用例

    1. 二维数组中包含查找的数字(査找的数字是数组中的最大值和最小值、査找的数字介于数组中的最大值和最小值之间);
    2. 二维数组中没有查找的数字(查找的数字大于数组中的最大值、査找的数字小于数组中的最小值、査找的数字在数组的最大值和最小值之间但数组中没有这个数字);
    3. 特殊输入测试(输入空指针)。

    例如有如下矩阵,给定 target = 5 返回 true,给定 target = 20,返回 false。

    [
      [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]
    ]
    

    解题思路

    这道题可以使用蛮力法来解决,也就是直接遍历二维数组,一个一个匹配需要查找的元素,这种方法的时间复杂度为 O(n^2)。不过由于传入的矩阵并不是规则的矩阵,只要是有规则的矩阵都可能找到更优的解法。其实对于矩阵的查找,也是一个解空间缩小的过程,使用蛮力法是在一个 n × n 的解空间中每次减少 1。因此总体的思路是如何更快地缩小解空间的大小,对于矩阵来说,如果可以一次性排除多个行或多个列,就可以降低解决问题的时间复杂度。
    设传入的 n × n 的矩阵中的任何一个元素是 x(i, j),其中 0 ≤ i < n 表示元素所在位置的行数,其中 0 ≤ j < n 表示元素所在位置的列数。由于矩阵的特性是“每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序”,因此从行的角度看,当任何一个元素 t < x(i, j) 时,该元素 t 必定小于元素 x(i + p, j) (i ≤ i + p < n)。同理从列的角度看,当任何一个元素 t > x(i, j) 时,该元素 t 必定大于元素 x(i, j - q) (0 ≤ j - q < j)。
    这么讲其实还是很抽象,这里引用 LeetCode 上这道题的第一条热门评论,来自用户 ymy1248:

    如何理解?也就是说如果把矩阵当做一个树结构,右上角的结点当做树的根结点,则满足 x(i - 1, j) < x(i + p, j) < x(i, j + 1),这恰好是一棵二叉搜素树。

    把这个矩阵旋转过来,就能更明显地看出来了,当在该搜索树中没下降一层,就可以减少一行或一列的解空间。值得一提的是,也可以将矩阵左下角的元素当做根结点,此时结点的左孩子是较大的数,右节点是较小的数。

    解题代码

    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int idx_x = matrix.size() - 1;
        int idx_y = 0;
    
        while(idx_x >= 0 && idx_y < matrix[0].size())
        {
            if(matrix[idx_x][idx_y] > target) 
            {
                idx_x--;
            }
            else if(matrix[idx_x][idx_y] < target)
            {
                idx_y++;
            }
            else
            {
                return true;
            }
        }
        return false;
    }
    

    时空复杂度

    按照二叉搜索树的方式扫描数组时,一次可以减少一行或一列的解空间,因此最坏情况是搜索完所有的行或列之后找不到。设矩阵是 N 行 N 列,则把每一行和每一列都遍历一遍的 T(n) = 2n,得时间复杂度 O(n)。
    由于没有使用辅助空间,因此空间复杂度 O(1)。

    参考资料

    《剑指 Offer(第2版)》,何海涛 著,电子工业出版社
    面试题04. 二维数组中的查找(标志数,清晰图解)

  • 相关阅读:
    json数组对象和对象数组
    C#中的List<string>泛型类示例
    Ajax异步更新网页(使用原生JavaScript)
    Ajax基础
    jQuery的动画效果
    jQuery事件绑定
    jQuery节点更新
    jQuery选择器
    json数据
    jQuery中的html()、text()和val()的用法
  • 原文地址:https://www.cnblogs.com/linfangnan/p/14571874.html
Copyright © 2020-2023  润新知