Given an array of integers 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]. For example, Given [5, 7, 7, 8, 8, 10] and target value 8, return [3, 4].
vector<int> searchRange(vector<int>& nums, int target)
{
vector<int> ret({ -1, -1 });
int N = nums.size();
if (N <= 0) return ret;
// search for the left bound
int left = 0, right = N - 1;
while (left < right)
{
// mid might == left
int mid = left + (right - left) / 2;
if (nums[mid] < target)
left = mid + 1;
else
right = mid;
}
if (nums[left] != target) return ret;
else ret[0] = left;
// search for the right bound
right = N - 1;
while (left < right)
{
// mid might == right
int mid = left + (right - left) / 2 + 1;
if (nums[mid] > target)
right = mid - 1;
else
left = mid;
}
ret[1] = right;
return ret;
}
1.二分法計算mid:mid = left + (right - left) / 2
,儘量不要使用mid = (left + right) / 2
,可能會導致溢出。
2.mid = left + (right - left) / 2
是向left偏移的:如果left
和right
中間隔着偶數個數,則mid
的位置是偏向left
一位的。
if (nums[mid] < target) left = mid + 1;
else right = mid;
所以當mid
的值大於或等於target
的時候,保持left
不動,right = mid
,因爲mid
會向left
偏移,所以最終會逼近左邊界。
3.計算右邊界的時候:
if (nums[mid] > target) right = mid - 1;
else left = mid;
一定要保證mid
是向right
偏移的,因此mid = left + (right - left) / 2 + 1
類似的題目:
35. Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You may assume no duplicates in the array. Here are few examples. [1,3,5,6], 5 → 2 [1,3,5,6], 2 → 1 [1,3,5,6], 7 → 4 [1,3,5,6], 0 → 0
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int left = 0, right = n - 1;
while (left <= right)
{
int mid = (left + right) / 2;
if (nums[mid] == target)
return mid;
if (nums[mid] < target)
left = mid + 1;
else
right = mid - 1;
}
return left;
}
其實這類題目就是考察對C++中的lower_bound和upper_bound的實現。
lower_bound是返回第一個大於或者等於val
。
template <class ForwardIterator, class T>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = distance(first, last);
while (count>0)
{
it = first; step = count / 2; advance(it, step);
if (*it<val)
{
first = ++it;
count -= step + 1;
}
else count = step;
}
return first;
}
upper_bound是返回第一個大於val
。
template <class ForwardIterator, class T>
ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& val)
{
ForwardIterator it;
iterator_traits<ForwardIterator>::difference_type count, step;
count = std::distance(first, last);
while (count>0)
{
it = first; step = count / 2; std::advance(it, step);
if (!(val<*it))
{
first = ++it; count -= step + 1;
}
else count = step;
}
return first;
}
another code for search for a range: 利用lower_bound
和upper_bound
.
vector<int> searchRange(vector<int>& nums, int target)
{
vector<int> res(2, -1);
int N = nums.size();
if (N <= 0) return res;
int count = N;
int first = 0;
while (count > 0)
{
int step = count / 2;
int num = nums[first + step];
if (num < target)
{
first += ++step;
count -= step;
}
else
count = step;
}
if (first >= N || nums[first] != target) return res;
else res[0] = first;
count = N - first;
while (count > 0)
{
int step = count / 2;
int num = nums[first + step];
if (!(target < num))
{
first += ++step;
count -= step;
}
else
count = step;
}
res[1] = --first;
return res;
}