34. 在排序数组中查找元素的第一个和最后一个位置
Posted 炫云云
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了34. 在排序数组中查找元素的第一个和最后一个位置相关的知识,希望对你有一定的参考价值。
34. 在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 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]
二分查找
思路与算法 : 二分查找
直观的思路肯定是从前往后遍历一遍。用两个变量记录第一次和最后一次遇见 target \\textit{target} target 的下标,但这个方法的时间复杂度为 O ( n ) O(n) O(n) ,没有利用到数组升序排列的条件。
查找最接近且小于 target 的元素
while (l <= r):
mid = l + (r-l)//2;
if(target > nums[mid])
l = mid + 1;
else #target <= nums[mid]
r = mid - 1;
# 循环结束后,r 指向最接近且小于 target 的元素的位置
# (若 r 下标越界,则表示不存在); l = r + 1
查找最接近且大于 target 的元素
while(l <= r):
mid = l + (r-l)//2;
if(target >= nums[mid])
l = mid + 1;
else
r = mid - 1;
#循环结束后,l 指向最接近且大于 target 的元素的位置
#(若 l 下标越界,则表示不存在); r = l - 1
由于数组已经排序,因此整个数组是单调递增的,我们可以利用二分法来加速查找的过程。
考虑 target \\textit{target} target 开始和结束位置,其实我们要找的就是数组中「第一个等于 target \\textit{target} target 的位置」(记为 leftIdx \\textit{leftIdx} leftIdx )和「第一个大于 target \\textit{target} target 的位置减一」(记为 rightIdx \\textit{rightIdx} rightIdx)。
定义一个二分查找,寻找 leftIdx \\textit{leftIdx} leftIdx 即为在数组中寻找第一个等于 target \\textit{target} target 的下标,寻找 rightIdx \\textit{rightIdx} rightIdx 即为在数组中寻找第一个大于 target \\textit{target} target 的下标,然后将下标减一,即为最后一个位置。
最后,因为 target \\textit{target} target 可能不存在数组中,因此我们需要重新校验我们得到的两个下标 leftIdx \\textit{leftIdx} leftIdx 和 rightIdx \\textit{rightIdx} rightIdx,看是否符合条件,如果符合条件就返回 [ leftIdx , rightIdx ] [\\textit{leftIdx},\\textit{rightIdx}] [leftIdx,rightIdx] ,不符合就返回 [ − 1 , − 1 ] [-1,-1] [−1,−1] 。
class Solution(object):
def searchRange(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
def binarySearch(nums, target):
left =0
right = len(nums) -1
while left<=right:
mid = left+(right-left)//2
if nums[mid]< target : # 应该继续向右边找,搜索区间变为 [mid+1, right]
left = mid +1
else:
right = mid-1 #应该继续向左边找 ,搜索区间变为 [left, mid -1] ,
#[5,7,7,8,8,10],target=8.
# 寻找第一个满足条件的点, 即使得right在满足target的数的最左边,即寻找8的左边界
return left
leftIdx = binarySearch(nums, target)
rightIdx = binarySearch(nums, target+1)-1
if leftIdx== len(nums) or nums[leftIdx] != target:
return [-1,-1]
else:
return [leftIdx, rightIdx]
参考
以上是关于34. 在排序数组中查找元素的第一个和最后一个位置的主要内容,如果未能解决你的问题,请参考以下文章
java刷题--34在排序数组中查找元素的第一个和最后一个位置
LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置 | Python
算法leetcode|34. 在排序数组中查找元素的第一个和最后一个位置(rust重拳出击)