package com.freetymekiyan.algorithms.level.medium;
import org.junit.Test;
/**
* Given a sorted array of integers, find the starting and ending position of a given target value.
* <p>
* Your algorithm's runtime complexity must be in the order of O(log n).
* <p>
* If the target is not found in the array, return [-1, -1].
* <p>
* For example,
* Given [5, 7, 7, 8, 8, 10] and target value 8,
* return [3, 4].
* <p>
* Company Tags: LinkedIn
* Tags: Binary Search, Array
* Similar Problems: (E) First Bad Version
*/
public class SearchForARange {
/**
* Binary Search.
* If search for start, round middle value down:
* | If nums[mid] < target, l = mid + 1.
* | If nums[mid] = target, r = mid, since start can be mid or further left.
* | If nums[mid] > target, r = mid.
* If search for end, round middle value up:
* | If nums[mid] < target, l = mid.
* | If nums[mid] = target, l = mid, since end can be mid or further right.
* | If nums[mid] > target, r = mid - 1.
*/
public int[] searchRange(int[] nums, int target) {
int lo = 0;
int hi = nums.length - 1;
while (lo < hi) {
int mid = lo + (hi - lo) / 2; // Round down.
if (nums[mid] >= target) {
hi = mid;
} else {
lo = mid + 1;
}
}
if (nums[lo] != target) { // Failed search, no lower bound.
return new int[]{-1, -1};
}
int start = lo; // Save the lower bound. Otherwise it would be changed later.
hi = nums.length - 1; // Reset upper bound.
while (lo < hi) {
int mid = lo + (hi - lo + 1) / 2; // Round up instead. Otherwise will stuck in loop.
if (nums[mid] > target) {
hi = mid - 1;
} else {
lo = mid;
}
}
if (nums[hi] != target) { // Failed search, no upper bound.
return new int[]{-1, -1};
}
return new int[]{start, hi};
}
@Test
public void testExamples() {
SearchForARange s = new SearchForARange();
int[] A = {1, 2, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int[] range = s.searchRange(A, 3);
System.out.println(range[0] + " ~ " + range[1]);
}
}