当前位置:网站首页>LeetCode50天刷题计划(Day 19—— 在排序数组中查找元素的第一个和最后一个位置(9.10-10.40)
LeetCode50天刷题计划(Day 19—— 在排序数组中查找元素的第一个和最后一个位置(9.10-10.40)
2022-08-10 11:01:00 【国际知名观众】
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
啊 好困 啊
一、题目
在排序数组中查找元素的第一个和最后一个位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
提示
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109
二、思路
由于时间复杂度的要求,考虑先二分搜索出一个解(O(logn)),然后向其前后扩散线性查找全部解。
但第二步可能会导致时间超限,故考虑用两次细节条件不同的二分查找依次找出前边界和后边界。
根据情况,每次选择可能出现目标值的一部分元素,就是二分查找的核心思想。比如:
【第一次】查找首次出现的target时(left=0,right=n-1,首边界re1)
mid=[(left+right)/2]向下取整
如果midtarget,那么首边界应在[left,mid](闭区间)中
如果mid<target,那么首边界应在[mid+1,right](闭区间)中
如果mid>target,那么首边界应在[left,mid-1](闭区间)中
使左右指针不断聚拢,直至相遇,如果相遇时该元素恰好值为target,则寻找成功,否则说明数组中没有此元素,查找失败
【第二次】mid=[(left+right)/2]向上取整【为了满足left、mid、right三者相同都是target的情况】
如果首次可以查找到target首边界,才需要进行第二次查找尾边界,否则直接返回即可(left=re1,right=n-1,尾边界re2)
如果midtarget,那么尾边界应在[mid,right](闭区间)中
如果mid<target,那么尾边界应在[mid+1,right](闭区间)中
如果mid>target,那么首边界应在[left,mid-1](闭区间)中
找到左右指针相遇的地方,就是尾边界
三、代码
1.二分+线性(python)
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
#很明显,还是用二分搜索 先找到一个然后向前后扩散!
n=len(nums)-1
center=-1
#二分搜索
left=0
right=n
while(left<=right):
mid=(left+right)//2
#print(left,right,mid)
if(nums[mid]==target):
center=mid
break
elif(nums[mid]>target):
right=mid-1
else:
left=mid+1
#向两边扩散
if(center==-1):
return [-1,-1]
else:
left=right=center
while(left>=1 and nums[left-1]==nums[center]):
left-=1
while(right+1<=n and nums[right+1]== nums[center]):
right+=1
return[left,right]
2.二分+二分
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
n=len(nums)-1 #尾下标值
if(n<0): #空列表
return [-1,-1]
re1=-1 #左边界
#第一次二分搜索
left=0
right=n
while(left<right):
mid=(left+right)//2 #向下取整
if(nums[mid]==target):
right=mid
elif(nums[mid]>target):
right=mid-1
else:
left=mid+1
#出循环时一定有left==right
if(nums[left]==target): #找到
re1=left
else: #没找到
return [-1,-1]
#第二次二分搜索
left=re1
right=n
while(left<right):
mid=(left+right+1)//2 #向上取整
if(nums[mid]==target):
left=mid
elif(nums[mid]>target):
right=mid-1
else:
left=mid+1
#一定能找到尾,直接返回
return [re1,left]
边栏推荐
- Nocalhost - 让云原生时代的开发更高效
- 建校仅11年就入选“双一流” ,这所高校是凭什么做到的?
- 从脚本到剪辑,影像大师亲授的后期制作秘籍
- 越折腾越好用的 3 款开源 APP
- mysql5.7 installation and deployment - yum installation
- 力扣练习——60 二叉搜索子树的最大键值和
- [Brave food, not afraid to write the linked list] The problem of the penultimate node of the linked list
- Hangdian Multi-School-Loop-(uncertainty greedy + line segment tree)
- 【勇敢饭饭,不怕刷题之链表】有序链表的合并
- 阻塞 非阻塞 poll机制 异步
猜你喜欢
随机推荐
内存问题难定位,那是因为你没用ASAN
Double.doubleToLongBits() method uses
Emulate stm32 directly with proteus - the programmer can be completely discarded
Several small projects that I have open sourced over the years
三相380V整流后的电压
Pycharm终端出现PS问题、conda或activate不是内部命令问题..
Open Office XML 格式里如何描述多段具有不同字体设置的段落
rider内Mono脚本找不到引用资源
模块九 - 设计电商秒杀系统
英特尔推送20220809 CPU微码更新 修补Intel-SA-00657安全漏洞
软件架构简介
Intel pushes 20220809 CPU microcode update to patch Intel-SA-00657 security vulnerability
Article take you understand interrupt the key driver of polling mechanism
机器学习之暴力调参案例
老板加薪!看我做的WPF Loading!!!
Kyligence 通过 SOC 2 Type II 审计,以可信赖的企业级产品服务全球客户
Nocalhost - 让云原生时代的开发更高效
C#实战:基于ItextSharp技术标签生成小工具
YTU 2894: G--我要去内蒙古大草原
暑期总结4