【算法-剑指 Offer】04. 二维数组中的查找(数组方法;排序;二分查找)

剑指 Offer 04. 二维数组中的查找 - 力扣(LeetCode)

文章更新:2021年10月12日10:00:53

问题描述及示例

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的题解

我的题解1(暴力解法:Array.some()&includes())

好吧,API选手参上~🤣,直接一行代码就搞定,而且看起来性能也不是很差,哈哈哈哈哈……(手动狗头保命🐶)

当然这种方法自然不是题目想考察的方向,而且也没有充分利用数组的有序特征。不过确实好使,实在搞不懂为啥要搞那么多花里胡哨的,哈哈哈……

有关这两个API的详细用法,可以参看下方的MDN文档:

参考:Array.prototype.some() - JavaScript | MDN
参考:Array.prototype.includes() - JavaScript | MDN

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var findNumberIn2DArray = function(matrix, target) {
  return matrix.some(cur => cur.includes(target));
};


提交记录
129 / 129 个通过测试用例
状态:通过
执行用时:72 ms, 在所有 JavaScript 提交中击败了75.77%的用户
内存消耗:40.7 MB, 在所有 JavaScript 提交中击败了61.15%的用户
时间:2021/10/12 10:05	

我的题解2(二分查找)

既然谈到对有序数组的查找,我第一反应想到的其实就是二分查找。其实本题也可以利用二分查找的思想,只不过和形式稍微有点不同。

之前做过二分查找的题目,可以参看下面的博客:

参考:【算法-LeetCode】704. 二分查找_赖念安的博客-CSDN博客

一般的二分查找都是反复更迭左右指针和中间指针的位置来进行查找,其核心原理就是利用了数组原本的有序性(假设为升序):如果当前中间指针指向的元素 mid 比目标元素 target 大,那么就可以推断 target 必然不在 mid 的左侧;反之则可以推断 target 必然不在 mid 的右侧。在而本题中的数组是二维的,且在两个维度上都具有有序性的特点。所以 mid 元素的移动轨迹大致就和矩阵的对角线重合。

因为本题中的数组元素大小是从左到右为升序且从上到下为升序。所以中间元素的起点设置为右上角元素。查找过程大致如下:

  1. 如果当前元素比目标元素小,则将中间指针向下移动一个单位;
    如果当前元素比目标元素大,则将中间指针向左移动一个单位。
  2. 重复上面的判断,直到中间指针指向矩阵外(返回 false)或者找到目标元素 target

详解请看下方注释:

/**
 * @param {number[][]} matrix
 * @param {number} target
 * @return {boolean}
 */
var findNumberIn2DArray = function(matrix, target) {
  // 如果矩阵为空,则直接返回false
  if(!matrix.length) {
    return false;
  }
  // 初始化中间指针指向矩阵右上角,注意本题的中间指针是由i、j两个分指针组成的
  let i = 0;
  let j = matrix[0].length - 1;
  // 开始搜寻,如果中间指针指向的元素在矩阵范围内,
  while(i < matrix.length && j >= 0) {
    // 则判断指针指向元素是否等于目标元素,如果是的话就直接返回true,标志矩阵中存在目标值
    if(matrix[i][j] === target) {
      return true;
    }
    // 如果当前元素小于目标元素,则将中间指针向下移动一个单位,反之则向左移动一个单位
    matrix[i][j] < target ? i++ : j--;
  }
  // 如果指针已经指向了矩阵外,则说明矩阵中没有目标元素,返回false
  return false;
};


提交记录
129 / 129 个通过测试用例
状态:通过
执行用时:76 ms, 在所有 JavaScript 提交中击败了57.96%的用户
内存消耗:40.9 MB, 在所有 JavaScript 提交中击败了26.24%的用户
时间:2021/10/12 11:02

上面的程序就充分利用了二维数组原来就是有序的这一特点。其核心思路和普通的二分查找是相通的。

官方题解

更新:2021年7月29日18:43:21

因为我考虑到著作权归属问题,所以【官方题解】部分我不再粘贴具体的代码了,可到下方的链接中查看。

更新:2021年10月12日11:03:10

参考:面试题04. 二维数组中的查找 - 二维数组中的查找 - 力扣(LeetCode)

【更新结束】

有关参考

更新:2021年10月12日10:10:40
参考:Array.prototype.some() - JavaScript | MDN
参考:Array.prototype.includes() - JavaScript | MDN
更新:2021年10月12日12:04:42
参考:【算法-LeetCode】704. 二分查找_赖念安的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值