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; } }