题目描述

在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

题目分析

图 1

如果没有头绪的话,很显然使用 暴力解法 是完全可以解决该问题的。

即遍历二维数组中的每一个元素,时间复杂度:O(n^2)。

其实到这里我们就可以发现,使用这种暴力解法并没有充分利用题目给出的信息。这个二维数组是有特点的。

  • 每一行都是递增
  • 每一列都是递增

图 2

解法

解法一:二分法

对于有序数组的查找问题而言,二分法是最容易想到的一个解法。

在这里,对每一行使用二分查找,时间复杂度为 O(nlogn) 。二分查找复杂度 O(logn),一共 n 行,所以是总体的时间复杂度是 O(nlogn) 。

解法二:规律法

根据二维数组由上到下,由左到右递增的规律。

从左下角开始遍历,如果当前值比 target 小则往右找,如果比 target 大则往上找,如果存在,必然可以找到目标数字。

即选取右上角或者左下角的元素 a[row] [col] 与 target 进行比较, 当target小于元素 a[row] [col] 时,那么 target 必定在元素 a 所在行的左边,让 col-- ;当 target 大于元素 a[row] [col] 时,那么 target 必定在元素 a 所在列的下边,让 row++ ;

图 3

代码如下:

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

解法三:二分规律法

将解法一和解法二进行结合:对每行每列都使用二分查找,此时的时间复杂度为 O(logn * logm)

图 4

比如查找数字 9,首先使用用二分查找选出一行,总共有 5 行,那么( 0 + 5 ) / 2 = 2,所以我们找出了第 2行为基准行。

图 5

接下来对这一行(即第 2 行)又使用二分查找, 找出这一行(即第 2 行)中最后一个比目标值小的值,这里是 6。

图 6

6 及其所在的行和列把这个矩形划分为 4 部分:

图 7

  1. 左上部分(图 7 灰色部分),包括所在行的左边部分和所在列的上边部分:这一部分是绝对不会有目标数字的。因为这部分数字肯定比 6 小,而 6 又是小于目标数字的,所以左上部分全部小于目标数字。也就是说这个区域的数字不需要再进行判断了。
  2. 右下部分(图 7 绿色部分),包括所在行的右边部分,但不包括所在列的下面部分, 这一部分也是绝对不会有目标数字的。因为这部分都比 6 右边的数字 11 大,而 11 又比目标数字 9 更大,所以右下部分全部都比目标数字大。也就是说这个区域的数字也不需要再进行判断了。
  3. 左下部分(图 7 蓝色部分),可能含有目标数字。
  4. 右上部分(图 7 棕色部分),可能含有目标数字。

这样,实际上筛选的区域就只剩下左下部分(图 7 蓝色部分)右上部分(图 7 棕色部分)这两块区域了,相比于解法二而言,使用这种解法平均情况下每一次查找,都可以把行和列的长度减少一半

代码如下:

public class Solution { public boolean Find(int target, int [][] array) { // 特殊情况处理 if (array == null || array.length == 0 || array[0].length == 0) { return false; } int h = array.length - 1; int w = array[0].length - 1; // 如果目标值小于最小值 或者 目标值大于最大值,那肯定不存在 if (array[0][0] > target || array[h][w] < target) { return false; } return binarySearchIn2DArray(array, target, 0, h, 0, w); } public static boolean binarySearchIn2DArray(int[][] array, int target, int startX, int endX, int startY, int endY) { if (startX > endX || startY > endY) { return false; } //首先,根据二分法找出中间行 int x = (startX + endX) / 2; //对该行进行二分查找 int result = binarySearch(array[x], target, startY, endY); //找到的值位于 x 行,result 列 if (array[x][result] == target) { return true; // 如果找到则成功 } //对剩余的两部分分别进行递归查找 return binarySearchIn2DArray(array, target, startX, x - 1, result + 1, endY) || binarySearchIn2DArray(array, target, x + 1, endX, startY, result); } public static int binarySearch(int[] array, int target, int start, int end) { int i = (start + end) / 2; if (array[i] == target || start > end) {  return i; } else if (array[i] > target) { return binarySearch(array, target, start, i - 1); } else { return binarySearch(array, target, i + 1, end); } }}

在数组中查找指定元素_剑指 offer 第一题: 二维数组中的查找相关推荐

  1. 《剑指offer》——04. 二维数组中的查找——暴力法、线性查找——java实现

    文章目录 1.题目描述 2.解决方法 (1)暴力法 (2)线性查找(右上角->左下角) 参考: 1.题目描述 2.解决方法 (1)暴力法 如果不考虑二维数组排好序的特点,则直接遍历整个二维数组的 ...

  2. 【剑指offer题解】二维数组中的查找

    前言 众所周知,对于面试而言,<剑指offer>是一本"好书". 如果你和我一样是个算法菜鸡,那么最推荐的是先把剑指offer的题目搞明白,其次再去刷LeetCode等 ...

  3. 【剑指offer】_01 (二维数组中的查找)

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  4. 剑指offer (04):二维数组中的查找 (C++ Python 实现)

    1 题目 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 例如: ⎡⎣⎢⎢⎢12 ...

  5. 萌萌媛の【剑指offer笔记】二维数组中的查找

    题目描述: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整 ...

  6. 剑指offer(一):二维数组中的查找

    题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. ...

  7. 剑指offer:2.二维数组的查找(Java版)

    备注:本文参照<剑指offer第二版> 题目: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数, 输入这样的一个二维数组和一个整数 ...

  8. java统计一个字符串中每个字符出现的次数_剑指offer算法题054:字符流中第一个不重复的字符...

    推荐阅读:宇宙条的工作总结:一年前还在面试找工作,一年后在面试找工作的学弟学妹们:第一次当面试官的经历分享小编在求职找找工作期间剑指offer上的算法题刷了很多遍,并且每道题小编当时都总结了一种最适合 ...

  9. 剑指offer算法题028:数组中出现次数超过一半的数字

    小编在求职找找工作期间剑指offer上的算法题刷了很多遍,并且每道题小编当时都总结了一种最适合面试时手撕算法的最优解法.考虑到剑指offer算法题在面试中的高频出现,小编每天和大家分享一道剑指offe ...

最新文章

  1. 巩固好基础,才能学好Linux
  2. 《自然》评价“天问一号”成功发射—— 全球深空探索走进新时代
  3. 对于出差的看法_我对于挑选背包的一些小建议
  4. 使用python写一个名片管理系统
  5. linux awk详解
  6. Qt 4.8.4 Qt Creator 2.6.1 安装和配置(Windows)
  7. 初入WEBOTS半个月来的一点总结
  8. 计算机专业英语的题目,计算机专业英语题目
  9. dnn神经网络 缺点_抄近路神经网络如何因找捷径而犯错
  10. linux VPS上装FTP
  11. 改变Tomcat的端口de方法
  12. sudo: unable to resolve host 枝桠
  13. 定时器/计数器0(定时器)
  14. 缓冲区提前释放,导致H264保存及播放错误
  15. 谈谈以前那位研发总监的工作
  16. mysql图书管理系统设计答辩_基于微信的图书管理系统毕业论文+任务书+开题报告+答辩PPT+前后台(Java+Mysql)源码及数据库文件...
  17. 计算机科普扫盲——固态硬盘
  18. SWI-Prolog的下载与使用
  19. ROS运行管理之launch文件
  20. 申论(基础题)之扫清阅读障碍和提取障碍

热门文章

  1. 1.2 String字符串和整型int的相互转换,valueOf() 、parse()和toString()
  2. 2021暑假每日一题 【week3 完结】
  3. jQuery的attr()和prop()方法
  4. WdatePicker控件的使用
  5. Servlet获取Web应用程序的初始化参数
  6. 我去,还在这样读写 excel 这也太低效了吧,好办法来了
  7. Java线程池原理及使用
  8. 映射文件xxx.hbm.xml下的各元素结构
  9. super关键字和final关键字
  10. 视图、索引、存储过程优缺点