Second solution is my favourite actually. But it seems that some interviewer prefer to do it recursively.
#include <iostream>
#include <vector>
using namespace std;
/*
Given a sorted arry of integers. Find the starting and ending position
of a given target value.
algorithm's run time should be in order of O(lgn)
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];
*/
// First solution. O(lgn) but worst time O(n).
vector<int> searchRange(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
vector<int> res;
while(left <= right) {
int mid = (left + right) / 2;
if(nums[mid] == target) {
int left = mid;
int right = mid;
while(nums[left] == target) {left--;}
while(nums[right] == target) {right++;}
if((nums[left+1] == target) && (nums[right-1] == target)) {
res.push_back(left+1);
res.push_back(right-1);
return res;
}
} else if(nums[mid] < target) left = mid + 1;
else right = mid - 1;
}
return {-1, -1};
}
int searchRangeRight(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while(left < right) {
int mid = (left + right + 1) / 2; // here should plus 1, make it moving.
if(nums[mid] > target) right = mid - 1;
else left = mid;
}
if(nums[left] == target) return left;
return -1;
}
int searchRangeLeft(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while(left < right) {
int mid = (left + right) / 2;
if(nums[mid] < target) left = mid + 1;
else right = mid;
}
if(nums[right] == target) return right;
return -1;
}
// Second solution. always O(lgn) even with repeations.
vector<int> searchRangeII(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
int leftIndex = searchRangeLeft(nums, target);
int rightIndex = searchRangeRight(nums, target);
return {leftIndex, rightIndex};
}
int searchRangeIII(vector<int>& nums, int left, int right, int target, bool flag) {
if(left > right) return -1;
int mid = (left + right) / 2;
if(nums[mid] == target) {
int pos = flag ? searchRangeIII(nums, left, mid - 1, target, flag) : searchRangeIII(nums, mid + 1, right, target, flag);
return pos == -1 ? mid : pos;
} else if(nums[mid] < target)
searchRangeIII(nums, mid + 1, right, target, flag);
else
searchRangeIII(nums, left, mid - 1, target, flag);
}
// Let's do it recursively....
vector<int> searchRangeIII(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
bool leftFlag = true;
int leftIndex = searchRangeIII(nums, left, right, target, leftFlag);
int rightIndex = searchRangeIII(nums, left, right, target, !leftFlag);
return {leftIndex, rightIndex};
}
int main(void) {
vector<int> nums{5, 7, 7, 8, 8, 10};
vector<int> res = searchRangeIII(nums, 7);
for(int i = 0; i < res.size(); ++i) {
cout << res[i] << endl;
}
}