题目描述:给定一个包含 n 个整数的排序数组,找出给定目标值 target 的起始和结束位置。如果目标值不在数组中,则返回[-1, -1]
样例:给出[5, 7, 7, 8, 8, 10]和目标值target=8,返回[3, 4]
还记得在学习二分查找时遇到的第一个问题吗?要求返回目标值第一次在数组中出现的位置,详见:点击打开链接。
那么现在问题就可以简化了:我们可以先通过二分法找到目标的任意一个位置,比如,在样例[5, 7, 7, 8, 8, 10]中8所在位置是3和4,我们找到任意一个位置(3或4)之后,在这一位将数组分割,例如,我们选择位于第3位的'8',将数组分割成[5, 7, 7, 8]和[8, 8, 10]两个部分,需要注意的是,两个数组都包含了我们选择的那个位,这样做的目的是防止其中一个数组完全不存在target.之后,再在向左边数组搜索target的第一个出现的位置,也就是target出现的区间的最左端的位置;在右边数组搜索target的最后一个出现的位置,也就是target出现的区间的最右端的位置。这两次查找都是二分法,其中,查找最左端位置的算法跟上面讲的那个问题一模一样,查找最右端位置的算法同理。
简单说,算法分为三步:
1. 二分法找到任意一个target
2. 以这个找到的target为分界线,将数组分成左右两部分
3. 分别查找左边数组最左端的target;右边数组最右端的target
代码照这个写就行:
class Solution: """ @param A : a list of integers @param target : an integer to be searched @return : a list of length 2, [index1, index2] """ def searchRange(self, A, target): left, right = 0, len(A) - 1 result = [] while left <= right: mid = (left + right) // 2 if A[mid] == target: result.append(self.lower_bound(A, left, mid, target)) result.append(self.upper_bound(A, mid, right, target)) return result elif A[mid] > target: right = mid - 1 else: left = mid + 1 return [-1, -1] def lower_bound(self, array, left, right, target): left, right = 0, len(array) - 1 while left <= right: mid = (left + right) // 2 if array[mid] >= target: right = mid - 1 else: left = mid + 1 return left def upper_bound(self, array, left, right, target): left, right = 0, len(array) - 1 while left <= right: mid = (left + right) // 2 if array[mid] <= target: left = mid + 1 else: right = mid - 1 return right # write your code here其中,lower_bound和upper_bound是分别向左右两边搜寻的函数,他们里面的形参left和right表示这两个数组的起止位置。由算法结构知:时间复杂度O(logn)