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

算法20.0

34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode)

目录

一、查找区间左端点

1.0 自己的理解

2.0 细节

3.0 别人的理解

(1)解法:

(2)细节处理:  循环条件和求中点操作  ​编辑

二、查找区间右端点

1.0 自己的理解

2.0 细节

3.0 别人的理解


一、查找区间左端点

1.0 自己的理解

为什么朴素二分法在这道题目时间复杂度很高?

朴素二分法能找到那个数字 但是不知道是第几个  需要向两边扩散 

此时最好的情况是目标值唯一  最坏的情况是目标值占满整个数组(3,3,3,3,3,3,3,3,3),此时需要遍历全部数  这样的话时间复杂度很高 极端情况下会超时 不推荐

查找区间左端点的时候 为什么分情况是小于一种 大于和等于一种 以及此时的结果情况是?

因为这个和朴素二分法不一样  此时的大于和等于不能分情况讨论了

找到的这个元素小于t可以确保左面那个区间扔了    然后left移动到mid+1

但是找到的这个元素等于  不一定这个元素就是要找的左端点 但是可以确保这个元素的右面一定有要找的右端点  更新的话不能让right直接到mid-1了(这时的mid有可能是最终结果)    要让right = mid

为什么循环条件是left<right 而不是left<=right ?

left的更新是mid+1 它一直想要跳出来  到mid右边

right的更新是mid   没有想要出来也出不来  一直是靠近mid最后成为mid

它们两个相遇的场景就是   就是最终找到的那个结果   无需判断

为什么left=right的时候判断    就会死循环?

因为right不动(right=mid)   left也不动  它们卡在那里一直循环(看星星标记下的2号情况)

为什么求中点操作只能用 left+(right-left)/2呢?

如果数组是奇数个的话    求得的中点只能是中间那个点

但是如果数组是偶数个的话    求中点的两个表达式  是不一样的结果 一个靠左的中点一个靠右的中点  在朴素二分法的时候都是可以的 但是这里不行

当最后一次操作的时候 数组里面只剩下两个元素 

用第二种方法求中点 mid落在右面那个  如果最后的判断中了星号的第一个条件

left到mid后面+1   超出去了 程序是会结束的

如果中了星号的第二个条件  x>=t  right=mid  下一步进入循环求中点的时候还是right到mid  死循环了

2.0 细节

审题:

//非递减:要么增要么不动  用图形化来表示是下面的样子

//题目最后给了特殊情况 如果是空的数组 我们返回-1就可以了   这个部分也是做题的一种情况

3.0 别人的理解
(1)解法:

暴力解法   从前面往后遍历 然后返回

尝试使用朴素的二分算法解决问题  发现有问题

尝试优化朴素二分法:二分的本质是二段性  要找到题目里的二段性

查找区间左端点的时候  发现了二段性

(x表示mid位置的值) 


(2)细节处理:  循环条件和求中点操作
  

求中点操作

防溢出  left+(right-left)/2   可以

left +(right-left+1)/2不行

二、查找区间右端点

和查找区间左端点的思路相同 但是有的地方细节不同

1.0 自己的理解

查找右区间端点 x<=t的时候 为什么是left=mid?

left不能越过去  因为越过的这个元素可能正是我们要找到元素

right的更新策略为什么是right=mid-1?

mid落在的区间一定是不符合要求的(就像是查找左区间 left一定想要跳出来 那个区间就没有 这里也一样  right也一直想要跳出这个区间 因为这个区间没有要找的点) 

2.0 细节
3.0 别人的理解

插播一个二分模板

下面是题目、效果图和代码:

class Solution {public int[] searchRange(int[] nums, int target) {//处理边界情况int[] ret = new int[2];ret[0] = ret[1] = -1;if(nums.length == 0 )  return ret;//1.二分左端点int left = 0 , right = nums.length-1;while(left<right){int mid = left+(right-left)/2;if(nums[mid]<target) left = mid +1;else right = mid;}//因为这个数组有可能有没有target  所以需要判断一下//判断是否有结果if(nums[left] != target) return ret;else ret[0]=right;//2.二分右面端点left = 0 ;right = nums.length-1;//因为已经找到区间的左端点 不需要从0开始 我们此时可以从左端点开始while(left<right){int mid = left+(right-left+1)/2;if(nums[mid]<=target) left = mid;else right = mid-1;}ret[1]=left;return ret;}
}
//xiyu251030&1#3*2

http://www.dtcms.com/a/548923.html

相关文章:

  • golang程序对接prometheus
  • 服务器负载均衡架构部署:Keepalived+Nginx 实现双机热备与高可用负载均衡
  • 内容分享网站设计在阿里巴巴上做网站有效果吗
  • SAP PP BOM主数据维护接口分享
  • 合成孔径雷达(SAR)及其信号处理:一文读懂,从类比到原理
  • 深度学习神经网络入门-问答学习
  • 化工防爆气象站:化工安全的气象监测设备
  • 做货运网站找哪家好如何用云服务器搭建个人网站
  • RAG拓展、变体、增强版(三)
  • 【PDF】PDF文件体详解
  • C++ STL list 容器学习笔记:双向链表的 “小火车“ 操控指南
  • Visual Studio Code (VS Code) 官方下载渠道
  • 网站制作的相关术语有哪些建一个网站多少钱
  • 企业网站建设属于什么费用搜索引擎优化的英文缩写
  • 告别“凭感觉”告警,金仓数据库替换MongoDB让运维更精准
  • 机器学习从业者大语言模型微调指南
  • Neo4j图数据库:简述增删改查
  • Mac版Color Folder v3.8安装教程(附dmg文件安装步骤和搜索关键词)
  • 金仓KES MongoDB兼容性深度解析与实践
  • Fiddler抓包实战教程 从安装配置到代理设置,详解Fiddler使用方法与调试技巧(HTTPHTTPS全面指南)
  • 对电子商务网站建设的感想4399网页游戏大全
  • 珠海专业医疗网站建设请人做ppt的网站
  • 印团网网站是哪家做的平面设计年终总结
  • 【u-boot】u-boot的I2C驱动框架剖析
  • JFrog vs Nexus vs Hadess,制品管理工具一文纵评
  • 【Docker】容器常用命令
  • Linux《Socket编程UDP》
  • Java IO 流进阶:Buffer 与 Channel 核心概念解析及与传统 IO 的本质区别
  • 【Linux基础开发工具 (一)】详解Linux软件生态与包管理器:从yum / apt原理到镜像源实战
  • 镇江网站营销推广电商怎么做如何从零开始视频