题目:
Given an array of integers nums
sorted in ascending order, find the starting and ending position of a given target
value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1]
.
Example 1:
Input: nums = [5,7,7,8,8,10]
, target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10]
, target = 6
Output: [-1,-1]
思路:
注意到这里要求严格的O(log n)时间复杂度。在此处可以采用传统的二分查找找到第一个目标元素,剩下的元素可从第一个目标元素的左边和右边依次二分查找。这样的确可以把时间复杂度控制在O(log n),不过中间、左边、右边三个地方的二分查找需要写三个二分查找的函数。放上一份二分查找的标准写法:
def binary_search(nums, lo, hi, target):
if lo > hi:
return -1
mid = (lo + hi) // 2
if nums[mid] > target:
mid = binary_search(nums, lo, mid - 1, target)
elif nums[mid] < target:
mid = binary_search(nums, mid + 1, hi, target)
return mid
反正都要找到target在序列中的左边界和右边界,为什么不直接查找左边界和右边界呢?更进一步,利用序列有序的特点,我们只需要找到target和target+1的左边界,就可以最初target的左右边界,并只用写一个搜索函数。(此处参考@vision57的解法)。在定义的子函数中,左边界为大于等于target值的第一个数。代码如下:
class Solution(object):
def searchRange(self, nums, target):
start = self.first_equal_greater_than_target(nums, 0, len(nums), target)
if start == len(nums) or nums[start] != target:
return [-1, -1]
end = self.first_equal_greater_than_target(nums, start, len(nums), target + 1)
return [start, end - 1]
def first_equal_greater_than_target(self, nums, lo, hi, target):
while lo < hi:
mid = (lo + hi) // 2
if nums[mid] < target:
lo = mid + 1
else:
hi = mid
return lo
有两个注意的点,第一个是查找是放入的右边界是len(nums)+1,用这个数据来标记异常(也就是没找到target);一个是查找target+1,用以间接获得右边界。