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

HOT100--Day22--74. 搜索二维矩阵,34. 在排序数组中查找元素的第一个和最后一个位置,33. 搜索旋转排序数组

HOT100–Day22–74. 搜索二维矩阵,34. 在排序数组中查找元素的第一个和最后一个位置,33. 搜索旋转排序数组

每日刷题系列。今天的题目是《力扣HOT100》题单。

题目类型:二分查找。

关键:

今天的题目都是“多次二分”

74题,掌握如何把有序矩阵,flatten成一维。

34题,懂得如何找元素的最左索引。

35题,懂得“翻转有序数组”的特性。如何找最小值的位置?要搜索怎么搜?

74. 搜索二维矩阵

思路:

先竖着二分,找到所在行,再横着二分,找到所在列。

class Solution {// 先竖着二分,再横着二分public boolean searchMatrix(int[][] matrix, int target) {int n = matrix.length;int m = matrix[0].length;int top = 0;int bottom = n - 1;int row = 0;while (top <= bottom) {row = top + ((bottom - top) >> 1);if (matrix[row][0] == target) {return true;} else if (matrix[row][0] > target) {bottom = row - 1;} else if (matrix[row][0] < target) {if (row == n - 1 || matrix[row + 1][0] > target) {break;}top = row + 1;}}int left = 0;int right = m - 1;while (left <= right) {int mid = left + ((right - left) >> 1);if (matrix[row][mid] == target) {return true;} else if (matrix[row][mid] > target) {right = mid - 1;} else if (matrix[row][mid] < target) {left = mid + 1;}}return false;}
}

思路:

flatten成一维。

关键:计算当前mid在矩阵中的什么位置int x = matrix[mid / m][mid % m];

class Solution {// 思路:flatten成一维的public boolean searchMatrix(int[][] matrix, int target) {int n = matrix.length;int m = matrix[0].length;int left = 0;int right = n * m - 1;while (left <= right) {int mid = left + ((right - left) >> 1);// 关键:计算当前mid在矩阵中的什么位置int x = matrix[mid / m][mid % m];if (x == target) {return true;}if (x < target) {left = mid + 1;} else {right = mid - 1;}}return false;}
}

思路:

排除法。

从右上角开始比较。

如果右上角元素小于target,那么这一行直接丢弃,i++,下一行。

如果右上角元素大于target,那么到了所在行了,j–,往左走到尽头。

class Solution {// 排除法public boolean searchMatrix(int[][] matrix, int target) {int n = matrix.length;int m = matrix[0].length;// 从右上角开始int i = 0;int j = m - 1;// 直到左下角while (i < n && j >= 0) {if (matrix[i][j] == target) {return true;}// 这里是右上角元素,证明这一行剩余元素全部小于 target,排除if (matrix[i][j] < target) {i++;} else {// 到所在行了,往左走。j--;}}return false;}
}

34. 在排序数组中查找元素的第一个和最后一个位置

思路:

多次二分:

先找到任意一个target的索引,从当前位置,往左往右不断二分找target,直到找到最左和最右值。

class Solution {public int[] searchRange(int[] nums, int target) {int n = nums.length;int[] res = { -1, -1 };int mid = findIndex(nums, 0, n - 1, target);if (mid == -1) {return res;} else {res[0] = mid;res[1] = mid;}int left = mid;int right = mid;while (left != -1 || right != -1) {left = findIndex(nums, 0, left - 1, target);res[0] = left != -1 ? left : res[0];right = findIndex(nums, right + 1, n - 1, target);res[1] = right != -1 ? right : res[1];}return res;}private int findIndex(int[] nums, int begin, int end, int target) {int left = begin;int right = end;while (left <= right) {int mid = left + ((right - left) >> 1);if (nums[mid] == target) {return mid;} else if (nums[mid] < target) {left = mid + 1;} else if (nums[mid] > target) {right = mid - 1;}}return -1;}
}

思路:

两次二分。

一次寻找最左的值为target的值

第二次寻找最左的,值为target+1的值。找不到不要紧,是那个位置就行了。减一就是target的最右边。

class Solution {public int[] searchRange(int[] nums, int target) {int start = findLeftest(nums, target);if (start == nums.length || nums[start] != target) {return new int[] { -1, -1 };}int end = findLeftest(nums, target + 1) - 1;return new int[] { start, end };}private int findLeftest(int[] nums, int target) {int left = 0;int right = nums.length - 1;while (left <= right) {int mid = left + ((right - left) >> 1);if (nums[mid] >= target) {right = mid - 1;} else {left = mid + 1;}}return left;}
}

33. 搜索旋转排序数组

思路:

两次二分。

第一次,先找到最小值的点,把它划分成两段,这两段都是单调的,可以用二分了。

从这两段里面分别二分,寻找target。

class Solution {public int search(int[] nums, int target) {int n = nums.length;int i = findMin(nums);if (target > nums[n - 1]) { // target 在第一段return lowerBound(nums, -1, i, target); // 开区间 (-1, i)}// target 在第二段return lowerBound(nums, i - 1, n, target); // 开区间 (i-1, n)}// 153. 寻找旋转排序数组中的最小值(返回的是下标)private int findMin(int[] nums) {int n = nums.length;int left = -1;int right = n - 1; // 开区间 (-1, n-1)while (left + 1 < right) { // 开区间不为空int mid = left + ((right - left) >> 1);if (nums[mid] < nums[n - 1]) {right = mid;} else {left = mid;}}return right;}// 有序数组中找 target 的下标private int lowerBound(int[] nums, int left, int right, int target) {while (left + 1 < right) { // 开区间不为空// 循环不变量:// nums[right] >= target// nums[left] < targetint mid = left + ((right - left) >> 1);if (nums[mid] >= target) {right = mid; // 范围缩小到 (left, mid)} else {left = mid; // 范围缩小到 (mid, right)}}return nums[right] == target ? right : -1;}
}

文章转载自:

http://s8SvOOWG.fkmyq.cn
http://IcMZrbXa.fkmyq.cn
http://0ZHdTktS.fkmyq.cn
http://9sCsuS9R.fkmyq.cn
http://kaMO983h.fkmyq.cn
http://Vcrq5YFh.fkmyq.cn
http://lIgyy5bB.fkmyq.cn
http://qKY17C0M.fkmyq.cn
http://50vZtW8Z.fkmyq.cn
http://FhvclG9j.fkmyq.cn
http://kR5p0VlT.fkmyq.cn
http://mAFipbHy.fkmyq.cn
http://vd0FTW7u.fkmyq.cn
http://fYhGLWrI.fkmyq.cn
http://qHgrjswQ.fkmyq.cn
http://yP2fQMhY.fkmyq.cn
http://B26HMqTx.fkmyq.cn
http://hp08U5He.fkmyq.cn
http://y5LTib6H.fkmyq.cn
http://vQq2chYG.fkmyq.cn
http://iUBySnGF.fkmyq.cn
http://cnFg20QR.fkmyq.cn
http://Gzaxp19H.fkmyq.cn
http://GpmIWcKs.fkmyq.cn
http://XiILrjNl.fkmyq.cn
http://96ANQNHn.fkmyq.cn
http://YTV5B34h.fkmyq.cn
http://73NI99kK.fkmyq.cn
http://4N3XL0VG.fkmyq.cn
http://qM6pi5KY.fkmyq.cn
http://www.dtcms.com/a/378685.html

相关文章:

  • Sentinel 原理与源码解析:流控、熔断、降级到热点限流的一体化方案
  • 克隆代币 + 捆绑开盘:多链环境下的低成本发币玩法
  • Android 项目:画图白板APP开发(六)——分页展示
  • 阿里云ClickHouse数据保护秘籍:本地备份与恢复详解
  • 数字图像处理——图像金字塔
  • 全球充电标准体系简介
  • Sub-GHz无线收发单片机,低功耗物联网通信的硬件“基石”
  • React18学习笔记(一) 创建React项目,JSX基础应用,案例:视频网站评论区
  • 【实时Linux实战系列】规避缺页中断:mlock/hugetlb 与页面预热
  • 全球汽车高压电加热器市场规模到2031年将达到62.72亿美元,CAGR 25.2%
  • 【展厅多媒体】从技术到体验,AR在展厅中的一体化整合
  • 双指针算法_移动零
  • 数据结构之复杂度
  • 几种常用锁
  • android13修改WiFi扫描二维码识别识别成功率不高的问题
  • params和body传参讲解
  • 单片机学习笔记
  • 图卷积神经网络(GCN)学习笔记
  • MySQL执行过程中如何选择最佳的执行路径
  • 牛客周赛 Round 108(思维、位运算、DP、SOSDP)
  • 插槽 el-input 数据双向 绑定失效 响应式更新失败
  • 代码随想录算法训练营第58天 | 拓扑排序精讲、dijkstra(朴素版)精讲
  • 揭秘KafkaStreams 线程缓存:NamedCache深度解析
  • 中标麒麟7.4部署gitlab-runner
  • Shopify指纹手机矩阵:无限扩店,横扫FB/GG广告封号风险
  • react context如何使用
  • npm是什么?优缺点又是什么?
  • ubuntu24.04+5070ti训练yolo模型(2)
  • [SQL]查询SSMS当前连接数据库列表
  • 乾博绝缘监测仪为水泥厂安全生产护航