题目描述:
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]
.
分析:
Search for a range:
pre: a inc list of int and the target val
post: the range for the val in the list of [-1,-1]
与普通的二分法要进行改进:
当mid的值与val值相同时,要从head->mid和从mid->tail中选出新的前后值
这里采取先选择head值,重复操作,直到head和tail对应的数据等于目标值val,退出循环。
class Solution:
def searchRange(self, nums, val):
head = 0
tail = len(nums)-1
mid = (head+tail)//2
while head < tail:
flag = 0
if ( nums[mid] < val ):
head = mid+1
mid = (head+tail)//2
elif nums[mid] > val :
tail = mid-1
mid = (head+tail)//2
elif nums[head] < val :
mid = (head+mid)//2
elif nums[tail] > val :
mid = (tail+mid)//2+1
else :
break
ans = []
if ( head >= len(nums) or nums[head] != val ):
ans.append(-1)
ans.append(-1)
else :
ans.append( head)
ans.append( tail )
return ans
另一思路:分两次寻找,分别寻找目标范围的head index和tail index
C++代码实现如下:
寻找head index和tail index的主要区别在于:1. mid的计算,向下取整或向上取整(目的是在不同的更新情况下达到收敛)。 2. 当nums[mid] == target时,如果寻找head index, 则更新right;如果是在寻找tail index,则更新left
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int left = 0, right = nums.size()-1 ;
vector<int> ans ;
// 寻找head index(nums的最左侧等于target的索引)
while( left < right ){
int mid = left + (right-left)/2 ;
if( nums[mid] >= target ){
right = mid ;
}else{
left = mid+1 ;
}
}
if( nums.size()>0 && nums[left] == target )
ans.push_back( left ) ;
else
ans.push_back( -1 ) ;
left = 0 ;
right = nums.size()-1 ;
// last position, how to end the loop
// 寻找tail index(nums的最右侧等于target的索引)
while( left < right ){
int mid = left + (right-left)/2 +1 ;
if( nums[mid] > target ){
right = mid-1 ;
}else{
left = mid ;
}
}
if( nums.size()>0 && nums[left] == target )
ans.push_back( left ) ;
else
ans.push_back( -1 ) ;
return ans ;
}
};