算法---LeetCode 74. 搜索二维矩阵

1. 题目

原题链接
编写一个高效的算法来判断 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

Related Topics 数组 二分查找
👍 446 👎 0

2. 题解

2.1 解法1: 从右上角开始搜索(与 240. 搜索二维矩阵 II 完全相同)

设坐标 x, y , 初始时为右上角,
当 坐标值 > target , y–
当 坐标值 < target, x++
当 坐标值 = target, 返回 true

    class Solution {
        public boolean searchMatrix(int[][] matrix, int target) {
            int m = matrix.length;
            int n = matrix[0].length;
            int row = 0;
            int col = n - 1;
            while (row < m && col >= 0) {
                if (matrix[row][col] == target) {
                    return true;
                } else if (matrix[row][col] < target) {
                    row++;
                } else {
                    col--;
                }
            }
            return false;
        }
    }

2.2 解法2: 两次二分

由于行列都有序, 第一次查找目标行, 第二次在目标行查找相应的列
第一次二分: 从上往下找, 找到最后一个 matrix<=target 的行
第二次二分: 从所在行中定位到列(从左到右,找到最后一个满足 matrix[row][x] <= target 的列号) 或者可以使用标准的二分查找代码

    class Solution {
        public boolean searchMatrix(int[][] matrix, int target) {
            if (matrix[0][0] > target) {
                return false;
            }
            int m = matrix.length, n = matrix[0].length;
            int left = 0, right = m - 1;
            while (left < right) { // 找到最后一个 matrix<=target 的行
                int mid = right + left + 1 >> 1;
                if (matrix[mid][0] > target) {
                    right = mid - 1;
                } else {
                    left = mid;
                }
            }
            int row = left;
            while (left <= right) {// 简单二分找元素是否存在
                int mid = right + left >> 1;
                if (matrix[row][mid] == target) {
                    return true;
                } else if (matrix[row][mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return false;
        }
    }
注意点:

开始写的时候有两种写法, 我写的第一种方式如下, 最后实际落在 第一个 >target 的元素上

int left = 0, right = m - 1;
while (left < right) {
    int mid = right + left >> 1;
    if (matrix[mid][0] > target) {
        right = mid;
    } else {
        left = mid + 1;
    }
}

第二种方式, 会直接落在 最后一个 <=target 的元素上

int left = 0, right = m - 1;
while (left < right) {
    int mid = right + left + 1 >> 1;
    if (matrix[mid][0] > target) {
        right = mid - 1;
    } else {
        left = mid;
    }
}

注意其中细小的差别, 1.mid 的计算 2.下一次 left 与 right下标的变化

根据题意选择第二种, 如果用第一种, 那么所需的下标为 left-1 , 这时要多考虑 只有一个元素的情况, 比如可能 left=0

总结: 两种写法都可以, 我个人一般用第一种比较多, 每次避免出错的办法就是 在草稿纸上推算一下, 一个元素及两个元素时的情况, 将所有情况都考虑到

2.3 解法3: 一次二分

主要思想与解法 1 类似, 因为将二维矩阵的行尾和行首连接,也具有单调性, 将二维数组通过下标转换 看成一维数组 进行二分查找即可
这里二维数组下标与 一维下标的关系如下(设n为数组的列数):
temp[mid]即为 matrix[mid/n][mid%n]

    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 = left + right >> 1;
                if (matrix[mid / n][mid % n] == target) {
                    return true;
                } else if (matrix[mid / n][mid % n] < target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return false;
        }
    }

参考:
【宫水三叶】一题双解:「二分」&「抽象 BST」解法
官方题解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值