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]
.
如下写法太丑陋了, 意思是先二分找到第一个K 然后左右再顺序查找扩展, 如果遇到数组都是 KKKKKK 那么时间复杂度还是0(N) ,如下写法加快了些,并不好,直到我在剑指offer 看到了类似的题目:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
vector<int> volidAns = { -1, -1 };
if (!nums.size()) return volidAns;
vector<int> ans;
int min = 0;
int max = nums.size() - 1;
int mid;
while (min <= max)
{
mid = (min + max) / 2;
if (nums[mid] == target)
{
search(mid, ans, nums);
return ans;
}
if (nums[mid] < target) min = mid + 1;
else
{
max = mid - 1;
}
}
}
private:
void search(int index, vector <int> & ans, vector<int>& nums)
{
int rightIndex = index;
int right = 1, left = 1;
int leftIndex = index;
int target = nums[index];
while (leftIndex >= 0 && nums[leftIndex] == target)
{
leftIndex -= left;
left *= 2;
}
left /=2;
leftIndex += left;
while (leftIndex >= 0 && nums[leftIndex] == target) --leftIndex;
++leftIndex;
ans.push_back(leftIndex);
while (rightIndex < nums.size() && nums[rightIndex] == target)
{
rightIndex += right;
right *=2;
}
right /= 2;
rightIndex -= right;
while (rightIndex < nums.size() && nums[rightIndex] == target) ++rightIndex;
--rightIndex;
ans.push_back(rightIndex);
}
};
int main()
{
vector<int> haha = { 1 };
Solution a;
vector <int> ans = a.searchRange(haha, 0);
for (int i = 0; i < ans.size(); ++i)
{
cout << ans[i] << " ";
}
system("pause");
return 0;
}
offer 写的比较棒 :