力扣 74. 搜索二维矩阵

问题描述

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

  • 每行中的整数从左到右按升序排列。
  • 每行的第一个整数大于前一行的最后一个整数。

示例1:

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true

示例2:

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 100
  • -104 <= matrix[i] [j], target <= 104

问题思路

思路1:两次顺序查找

​ 由题目可知,每一行、每一列的元素都是单调递增的。因此,可以首先对第一行进行一次顺序扫描,找到 target 可能存在的行,然后对那一行进行再一次的顺序扫描,即可得到结果。

​ 实现代码如下,空间复杂度O(nm),时间复杂度O(1)。运行时间0 ms。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int n = matrix.length;
        for(int i = 0; i < n; i++){
            if(i == n - 1 || matrix[i+1][0] > target){
                for(int j = 0; j < matrix[0].length; j++){
                    if(matrix[i][j] == target){
                        return true;
                    }
                }
            }
        }
        return false;
    }
}
思路2:两次二分查找

​ 思路1用到了顺序扫描,效率低下,可以考虑改成二分查找,降低算法时间复杂度。

​ 实现代码如下,空间复杂度O(log m + log n)= O(log mn),时间复杂度O(1)。运行时间0 ms。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int row = findRow(matrix, target);
        if(row < 0){
            return false;
        }
        int col = findCol(matrix[row], target);
        if(matrix[row][col] == target){
            return true;
        }else{
            return false;
        }
    }
    public int findRow(int[][] matrix, int target){
        int left = -1;
        int right = matrix.length - 1;
        while(left < right){
            int mid = (right - left + 1) / 2 + left;
            if(matrix[mid][0] > target){
                right = mid - 1;
            }else{
                left = mid;
            }
        }
        return left;
    }
    public int findCol(int[] array, int target){
        int left = 0;
        int right = array.length - 1;
        while(left < right){
            int mid = (right + left) / 2;
            if(array[mid] < target){
                left = mid + 1;
            }else{
                right = mid;
            }
        }
        return left;
    }
}
思路3:一次二分查找

​ 对思路2的代码可以进一步简化,即如果将matrix的每一行末尾与下一行开头进行拼接,就得到一个长度为mn的递增序列,我们对这个递增序列进行一次二分查找,即可得到结果。

​ 实现代码如下,空间复杂度 O(log mn),时间复杂度O(1)。运行时间0 ms。

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length
        int n = matrix[0].length;
        int left = 0;
        int right = m * n - 1;
        while (left <= right) {
            int mid = (right - left) / 2 + left;
            int x = matrix[mid / n][mid % n];
            if (x < target) {
                left = mid + 1;
            } else if (x > target) {
                right = mid - 1;
            } else {
                return true;
            }
        }
        return false;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值