剑指 Offer 04. 二维数组中的查找

题目

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

示例:
现有矩阵 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。
给定 target = 20,返回 false。
限制:
0 <= n <= 1000
0 <= m <= 1000

思路

主要分为几个思考方向:

  1. 暴力遍历
    直接对二维数组matrix[][]进行遍历,如果matrix[i][j] == target,就return true;否则,在退出便利的循环以后,return false;(此时表明:二维数组中不包含该target)

时间复杂度:O(nm)

  1. 线性查找
    因为二维数组的分布规律为:每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
    == >
    可以从二维数组的左下角或右上角进行分析。
    假设现在从右上角进行分析:
    对于右上角的元素matrix[0][m-1],与target之间的关系分为三种:>、<、==
    (1)如果 matrix[0][m-1] > target,因为每一列都按照从上到下递增的顺序,所以该列的所有元素都比target大,舍弃该列的所有元素;
    (2)如果 matrix[0][m-1] < target,因为每一行都按照从左到右递增的顺序,所以该行的所有元素都比target小,舍弃该行的所有元素;
    (3)如果 matrix[0][m-1] == target,则,直接return true;
    ---->将上面的判断过程写进一个循环里边,循环的判断条件为:
    while(row <= n-1 && col >= 0)
    其中,row的初始值为0;col的初始值为m-1。
    ----
    时间复杂度:O(n + m) 。最多循环n + m次。因为最坏的情况就是最后才找到。
    空间复杂度:O(1)。因为两个索引指针需要常数阶的额外空间。
  2. 二叉搜索树【二叉排序树】
    将矩阵逆时针旋转 45° ,并将其转化为图形式,发现其类似于 二叉搜索树 ,即对于每个元素,其左分支元素更小、右分支元素更大。因此,通过从 “根节点” 开始搜索,遇到比 target 大的元素就向左,反之向右,即可找到目标值 target 。
    在这里插入图片描述
    “根节点” 对应的是矩阵的 “左下角” 和 “右上角” 元素,本文称之为 标志数 ,以 matrix 中的 左下角元素 为标志数 flag ,则有:
    (1)若 flag > target ,则 target 一定在 flag 所在 行的上方 ,即 flag 所在行可被消去。
    (2)若 flag < target ,则 target 一定在 flag 所在 列的右方 ,即 flag 所在列可被消去。

实际上,实现起来,跟上边的“线性查找”是一样的!!!


时间复杂度:O(n + m) 。最多循环n + m次。因为最坏的情况就是最后才找到。
空间复杂度:O(1)。因为两个索引指针需要常数阶的额外空间。

代码实现

1、 暴力遍历

2、 线性查找(实现的代码与“3、”的一样)
3、 二叉搜索树【二叉排序树】

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {

        //如果该数组为空,或该数组不含有元素
        if(matrix == null || matrix.length == 0){
            return false;
        }

        // int n = matrix.length;
        int row = 0;//行的索引
        int col = matrix[0].length - 1;//列的索引
        while(row <= matrix.length-1 && col >= 0) {//matrix中的元素还没有判断完
            if(matrix[row][col] > target){
                //target比该元素小,舍弃该列的所有元素
                col -= 1;
            } else if(matrix[row][col] < target){
                //target比该元素大,舍弃该行的所有元素
                row += 1;
            } else {
                //找到了!!!
                return true;
            }
        }
        return false;
    }
}


学习:
当需要解决一个复杂问题时,一个很有效的办法就是:从一个具体的问题入手,通过分析简单具体的例子,试图寻找普遍的规律。
静下心来,动起手来,不要空想;
将所给的题干,结合具体的实例走一遍
==>会有意想不到的收获!!!!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值