【Java】每日一题,某扣二维数组中的查找

在一个 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

思路分析

首先每一行从左至右和每一行从上至下都不是递减的,想要在这个二维数组中判断目标值是否存在,暴力法是行的通的,但是这样做时间复杂度就会达到O(nm),看到题目中的条件,我最先能想到的方法就是使用二分查找法,对每一行都进行二分查找,判断target是否在此行中,但是这种方法并没有使用到每一列从上至下也是非递减的方式,因此这种方法必然也不是最优解,这里我先给出我的二分查找法进行求解,最后在说说我对最优解的理解。

二分查找法

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        for(int[] row : matrix){
            if(search(row,target)){ //调用search方法进行查找
                return true; //if判断为true说明查找到了目标值,直接返回
            }
        }
        return false;
    }
    private boolean search(int[] row,int target){ //二分查找法
        int l = 0;                //左指针
        int r = row.length - 1;   //右指针
        while(l <= r){           //结束条件
            int m = (l + r) / 2;  //中间位置
            if(row[m] == target){
                return true;
            }else if(row[m] < target){
                l = m + 1;
            }else{
                r = m - 1;
            }
        }
        return false;
    }
}

二分查找法的时间复杂度相对于暴力解法使用提升的,但这还并不是这道题的最优解,看了大神的题解以后顿时觉得自己和大神的差距是相隔万里的,还是好好学学大神的思路吧。

大神解法

将矩阵逆时针旋转 45° ,并将其转化为图形式,发现其类似于 二叉搜索树 ,即对于每个元素,其左分支元素更小、右分支元素更大。因此,通过从 “根节点” 开始搜索,遇到比 target 大的元素就向根节点左方搜索,反之向根节点右方搜索,即可找到目标值 target 。

 我们假设右上角的元素为标志数flag--即根节点,若flag > target,那么我们就应该向标志数的左方进行查找,那么标志数所在的列就可以被舍弃,反之flag < target,我们就应该向标志数的右方进行查找,那么标志数所在的行就可以被舍弃。代码如下:

class Solution {
    public boolean findNumberIn2DArray(int[][] matrix, int target) {
        if(matrix.length == 0){  //如果二维数组为空,直接返回false
            return false;
        }
        int i = 0;                     //标志数所在行
        int j = matrix[0].length - 1;  //标志数所在列
        while(j >= 0 && i < matrix.length){
            if(matrix[i][j] > target){  //目标值小于标志数
                j--;                    //舍弃标志数所在列
            }else if (matrix[i][j] < target){    //目标值大于标志数
                i++;                             //舍弃标志数所在行
            }else{
                return true;
            }
        }
        return false;
    }
   
}
  • 时间复杂度 O(M+N)O(M+N)O(M+N) :其中,NNN 和 MMM 分别为矩阵行数和列数,此算法最多循环 M+NM+NM+N 次。
  • 空间复杂度 O(1) : ij 指针使用常数大小额外空间。

这个解法最关键的点在与二维数组的行与列均是非递减的形式,联想到旋转二维数组很好的将题目中所给的条件应用到,从而降低时间复杂度。

大神解法参考自:https://leetcode.cn/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/solutions/95306/mian-shi-ti-04-er-wei-shu-zu-zhong-de-cha-zhao-zuo/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值