当前位置: 首页 > news >正文

力扣 搜索二维矩阵

二分查找,闭区间与开区间的不同解法。

题目

乍一看,不是遍历一下找到元素就可以了。

class Solution {public boolean searchMatrix(int[][] matrix, int target) {for (int[] ints : matrix) {for (int ans : ints) {if (ans == target) return true;}}return false;}
}

可以通过的,但还是可以优化一下的。这题可以用二分的思路,可以把整个矩阵看成一大个数组,若将矩阵每一行拼接在上一行的末尾,则会得到一个升序数组,我们可以在该数组上二分找到目标元素。但是这种方法在每一行元素个数不一时会失效。

时间复杂度:O(logmn),空间复杂度:O(1)。

class Solution {public boolean searchMatrix(int[][] matrix, int target) {int m = matrix.length, n = matrix[0].length;int low = 0, high = m * n - 1;while (low <= high) {int mid = (high - low) / 2 + low;int x = matrix[mid / n][mid % n];if (x < target) {low = mid + 1;} else if (x > target) {high = mid - 1;} else {return true;}}return false;}
}

以上为标准二分查找的写法,其中首尾做为边界,条件时while (low <= high),接着如果目标值偏大则在右边找,即low = mid + 1,反之,目标值偏小时往左边找,即 high = mid - 1,然后当low指针从左边到target时扫了一遍,当high指针从右边到target时扫了一遍,当两个指针重叠相遇时,进一步判断两个指针定住的数是不是目标数,然后退出循环。

这题还可以先对行二分,再对列二分,进行两次二分查找。每行的第一个元素大于前一行的第一个元素,矩阵第一列的元素是升序的。对矩阵的第一列的元素二分查找,找到最后一个不大于目标值的元素,然后在该元素所在行中二分查找目标值是否存在。

时间复杂度:O(logmn),空间复杂度:O(1)。

class Solution {public boolean searchMatrix(int[][] matrix, int target) {int rowIndex = binarySearchFirstColumn(matrix, target);if (rowIndex < 0) {return false;}return binarySearchRow(matrix[rowIndex], target);}public int binarySearchFirstColumn(int[][] matrix, int target) {int low = -1, high = matrix.length - 1;while (low < high) {int mid = (high - low + 1) / 2 + low;if (matrix[mid][0] <= target) {low = mid;} else {high = mid - 1;}}return low;}public boolean binarySearchRow(int[] row, int target) {int low = 0, high = row.length - 1;while (low <= high) {int mid = (high - low) / 2 + low;if (row[mid] == target) {return true;} else if (row[mid] > target) {high = mid - 1;} else {low = mid + 1;}}return false;}
}

其中,用了一个左开右闭区间的二分查找,可以先进行扩充边界,然后条件改为while (low < high),接着low要设置为mid,退出的条件即当low跟high重叠时,此时的low是mid了,看是不是要找的target。当然,这题用左闭右开区间的二分查找也是类似,不过要注意以下返回值,要取到不大于目标值的最大行索引。

class Solution {public boolean searchMatrix(int[][] matrix, int target) {int rowIndex = binarySearchFirstColumn(matrix, target);if (rowIndex < 0) {return false;}return binarySearchRow(matrix[rowIndex], target);}
public int binarySearchFirstColumn(int[][] matrix, int target) {int low = 0, high = matrix.length;  while (low < high) {  int mid = (high - low) / 2 + low;  if (matrix[mid][0] <= target) {  low = mid + 1;} else {  high = mid;  }}return high-1; 
}public boolean binarySearchRow(int[] row, int target) {int low = 0, high = row.length - 1;while (low <= high) {int mid = (high - low) / 2 + low;if (row[mid] == target) {return true;} else if (row[mid] > target) {high = mid - 1;} else {low = mid + 1;}}return false;}
}

然后,也可以用最经典的标准二分模板去写。

class Solution {public boolean searchMatrix(int[][] matrix, int target) {int rowIndex = binarySearchFirstColumn(matrix, target);if (rowIndex < 0) {return false;}return binarySearchRow(matrix[rowIndex], target);}
public int binarySearchFirstColumn(int[][] matrix, int target) {// 初始化low为0,high为矩阵最后一行的索引int low = 0, high = matrix.length - 1;while (low <= high) {  // 当low不大于high时继续循环int mid = (high - low) / 2 + low;  // 计算中间位置// 如果中间位置的行的第一个元素小于或等于目标值,则该行及之后的行可能是候选行if (matrix[mid][0] <= target) {low = mid + 1;  } else {high = mid - 1; }}// 返回不大于目标值的最大行索引return high;  // 这里返回high,因为high指向的是不大于目标值的最大行索引或未找到返回-1}public boolean binarySearchRow(int[] row, int target) {int low = 0, high = row.length - 1;while (low <= high) {int mid = (high - low) / 2 + low;if (row[mid] == target) {return true;} else if (row[mid] > target) {high = mid - 1;} else {low = mid + 1;}}return false;}
}

二分查找模板巧记,先写好数组中的左右边界值,然后while (low <= high),接着写mid的求值 int mid = (high - low) / 2 + low,再到判断,若目标值偏大往大的找即low指针右移,若目标值偏小往小的找即high指针左移,最后当low跟high重叠时对当前元素做判断,返回值依题而定。

http://www.lryc.cn/news/522490.html

相关文章:

  • JavaScript 操作符与表达式
  • 深度学习 Pytorch 张量(Tensor)的创建和常用方法
  • 在VMwareFusion中使用Ubuntu
  • %.*s——C语言中printf 函数中的一种格式化输出方式
  • 基于微信小程序的摄影竞赛系统设计与实现(LW+源码+讲解)
  • hydra破解密码
  • JAVA之外观模式
  • 如何选择合适的服务器?服务器租赁市场趋势分析
  • CentOS 下载软件时报Error: Failed to synchronize cache for repo ‘AppStream‘解决方法
  • 鲍厚霖:引领AI广告创新,搭建中美合作桥梁
  • 学习记录1
  • 【Gossip 协议】Golang的实现库Memberlist 库简介
  • LDD3学习7--硬件接口I/O端口(以short为例)
  • openharmony电源管理子系统
  • 【Rust自学】13.4. 闭包 Pt.4:使用闭包捕获环境
  • 在 macOS 上,用命令行连接 MySQL(/usr/local/mysql/bin/mysql -u root -p)
  • mono3d汇总
  • K8S 节点选择器
  • 【2024年华为OD机试】 (C卷,200分)- 反射计数(Java JS PythonC/C++)
  • AI编程工具使用技巧——通义灵码
  • 挖掘机检测数据集,准确识别率91.0%,4327张原始图片,支持YOLO,COCO JSON,PASICAL VOC XML等多种格式标注
  • 使用Docker部署postgresql
  • LabVIEW时域近场天线测试
  • LabVIEW桥接传感器数据采集与校准程序
  • 菜品管理(day03)
  • 深入理解 Android 混淆规则
  • 《Keras 3 在 TPU 上的肺炎分类》
  • 从 Android 进行永久删除照片恢复的 5 种方法
  • SDL2:Android APP编译使用
  • linux systemd 服务连续启动失败,不会再重启分析