每日一题——搜索二维矩阵

本文介绍如何高效地判断一个m x n的二维矩阵中是否存在目标值,通过二分法,分析两种实现思路:一是行和列分别二分,二是将矩阵视为一维数组整体二分。虽然时间复杂度看似不同,但实际并无本质区别。
摘要由CSDN通过智能技术生成

菜鸡每日一题系列打卡74

每天一道算法题目 

小伙伴们一起留言打卡

坚持就是胜利,我们一起努力!

题目描述(引自LeetCode)

编写一个高效的算法来判断m x n矩阵中,是否存在一个目标值。该矩阵具有如下特性:

  • 每行中的整数从左到右按升序排列。

  • 每行的第一个整数大于前一行的最后一个整数。

示例 1:
输入:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 3
输出: true
示例 2:
输入:
matrix = [
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]
target = 13
输出: false

题目分析

这明显是一道二分法的题目。我们可以采用两种思路来实现:一种是先对行进行二分,找到target可能在的行,然后再对列进行二分,判断target是否存在。另一种是对所有的数当作一维有序数组进行二分,然后映射到二维数组的对应坐标中。

Talk is cheap,菜鸡将采用上述两种方法进行实现。话不多说,上代码!

代码实现

class Solution {


    public boolean searchMatrix(int[][] matrix, int target) {
        // 特殊情况处理
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;


        int rowStart = 0, rowEnd = matrix.length - 1, rowMid = 0;
        int colStart = 0, colEnd = matrix[0].length - 1;


        // 二分法寻找行
        while (rowStart <= rowEnd) {
            rowMid = rowStart + ((rowEnd - rowStart) >> 1);
            if (matrix[rowMid][0] == target) return true;
            else if (matrix[rowMid][0] > target) rowEnd = rowMid - 1;
            else if (matrix[rowMid][colEnd] < target) rowStart = rowMid + 1;
            else break;
        }


        // 二分法寻找列
        while (colStart <= colEnd) {
            int colMid = colStart + ((colEnd - colStart) >> 1);
            if (matrix[rowMid][colMid] == target) return true;
            else if (matrix[rowMid][colMid] > target) colEnd = colMid - 1;
            else colStart = colMid + 1;
        }


        return false;
    }


}
class Solution {


    public boolean searchMatrix(int[][] matrix, int target) {
        // 特殊情况处理
        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;


        int m = matrix.length;
        int n = matrix[0].length;


        // 二分法
        int start = 0, end = m * n - 1;
        while (start <= end) {
            // 按照一维数组来计算中间坐标
            int mid = start + ((end - start) >> 1);
            // 定位中间坐标所在行
            int row = mid / n;
            // 定位中间坐标所在列
            int column = mid % n;
            // 比较判断
            if (matrix[row][column] == target) return true;
            else if (matrix[row][column] > target) end = mid - 1;
            else start = mid + 1;
        }
        return false;
    }


}

代码分析

对代码进行分析,第一种实现方式,对行和列分别进行二分,时间复杂度为O(max(logm, logn)),空间复杂度为O(1);第二种实现方式,对所有数字进行二分,然后映射到具体的二维数组坐标,时间复杂度为O(log(mn)),空间复杂度为O(1)。

乍一看,觉得第一种实现方式的时间复杂度好像更低一些,其实只要稍加分析,对于第二种实现方式,log(mn) = logm + logn,就会发现,这只是个数学游戏而已,两种实现方式的时间复杂度并无本质区别。

执行结果

对行和列分别进行二分的执行结果

对所有数字进行二分然后进行下标映射的执行结果

学习 | 工作 | 分享

????长按关注“有理想的菜鸡

只有你想不到,没有你学不到

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值