当前位置:网站首页>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]
边栏推荐
- Do self-media monthly income tens of thousands?Several self-media tools that bloggers are using
- LeetCode_443_压缩字符串
- 自媒体爆款标题怎么写?手把手教你写热门标题
- Programmers pursue technology to consolidate basic learning route suggestions
- StoneDB 文档捉虫活动第一季
- Some tips for using Unsafe
- WeChat applet, global variables change in one place and the state in other places also changes.
- 不止跑路,拯救误操作rm -rf /*的小伙儿
- 今天面了个腾讯拿38K出来的大佬,让我见识到了基础的天花板
- POJ 1026 Cipher (置换群)
猜你喜欢
随机推荐
C#实战:基于ItextSharp技术标签生成小工具
中小规模网站架构
Weilai-software development engineer side record
POJ 1026 Cipher (Permutation Groups)
Intel pushes 20220809 CPU microcode update to patch Intel-SA-00657 security vulnerability
Spss-多元回归案例实操
Gartner reiterates the important value of 'data weaving'
Will SQL and NoSQL eventually converge?
自媒体爆款标题怎么写?手把手教你写热门标题
WeChat applet, global variables change in one place and the state in other places also changes.
SQL优化最强总结 (建议收藏~)
面试官:项目中 Dao、Service、Controller、Util、Model 怎么划分的?
快手“弃”有赞与微盟“结亲”,电商SaaS行业竞争格局将变?
什么是抽象类
AutoCAD Map 3D功能之一暴力处理悬挂点(延伸)
LAXCUS分布式操作系统安全管理
老板加薪!看我做的WPF Loading!!!
蔚来-软件开发工程师一面记录
mysql appears: ERROR 1524 (HY000): Plugin '123' is not loaded
机器学习之暴力调参案例