/**************************************************************************
*
* 34. [Find First and Last Position of Element in Sorted Array]
* (https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/)
*
* Given an array of integers nums sorted in ascending order,
* find the starting and ending position of a given target value.
* If target is not found in the array, return [-1, -1].
*
* You must write an algorithm with O(log n) runtime complexity.
*
* Example 1:
* Input: nums = [5,7,7,8,8,10], target = 8
* Output: [3,4]
*
* Example 2:
* Input: nums = [5,7,7,8,8,10], target = 6
* Output: [-1,-1]
*
* Example 3:
* Input: nums = [], target = 0
* Output: [-1,-1]
**************************************************************************/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//
//
/// Approch 1: binary searches for target, then expand it
int *searchRange(int *nums, int numsSize, int target, int *returnSize) {
if (NULL == returnSize) return NULL;
*returnSize = 2;
int *res = (int *)calloc(2, sizeof(int));
res[0] = -1;
res[1] = -1;
if (NULL == nums || numsSize <=0 || target < nums[0] || target > nums[numsSize - 1])
return res;
int left = 0;
int right = numsSize - 1;
while (left < right) {
int mid = (left + right) / 2;
if (target == nums[mid]) {
left = mid;
right = mid;
} else if (target > nums[mid]) {
left = mid + 1;
} else {
right = mid - 1;
}
}
if (target != nums[left]) return res;
res[0] = left;
res[1] = right;
for (int i = left - 1; i >= 0; i--) {
if (nums[i] != target) {
res[0] = i + 1;
break;
} else {
res[0]--;
}
}
for (int i = right + 1; i < numsSize; i++) {
if (nums[i] != target) {
res[1] = i - 1;
break;
} else {
res[1]++;
}
}
return res;
}
//
//
/// Approch 2: twice binary searches
int *searchRange(int *nums, int numsSize, int target, int *returnSize) {
if (NULL == returnSize)
return NULL;
*returnSize = 2;
int *res = (int *)calloc(2, sizeof(int));
res[0] = -1;
res[1] = -1;
if (NULL == nums || numsSize <= 0 || target < nums[0] || target > nums[numsSize - 1])
return res;
int left = 0;
int right = numsSize - 1;
// Search for the left one
while (left < right) {
int mid = (left + right) / 2;
if (nums[mid] < target)
left = mid + 1;
else
right = mid;
}
if (nums[left] != target)
return res;
res[0] = left;
right = numsSize - 1;
// Search for the right one
while (left < right) {
int mid = (left + right) / 2 + 1; // Make mid biased to the right
if (nums[mid] > target)
right = mid - 1;
else
left = mid; // So that this won't make the search range stuck.
}
res[1] = right;
return res;
}
//
//
/// Approch 3: STL
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
if (nums.size() == 0)return { -1,-1 };
if (target<nums[0] || target>nums[nums.size() - 1])return {-1, -1};
const int l = distance(nums.begin(), lower_bound(nums.begin(), nums.end(), target));
const int u = distance(nums.begin(), prev(upper_bound(nums.begin(), nums.end(), target)));
if (nums[l] != target) // not found
return vector<int> {-1, -1};
else
return vector<int> {l, u};
}
};