Input: arr[] = {5, 6, 1, 2, 3, 4}
Output: 6
Explanation: 6 is the maximum element present in the array.
Input: arr[] = {3, 2, 2, 2}
Output: 3
Explanation: 3 is the maximum element present in the array.
In Binary Search, we find the mid element and then decide whether to stop or to go to left half or right half. How do we decide in this case. Let us take few examples.
{4, 5, 6, 9, 10, 1, 2}, mid = (0 + 7) / 2 = 3. arr[3] is 9. How to find out that we need to go to the right half (Note that the largest element is in right half)? We can say if arr[mid] > arr[lo], then we go the right half. So we change low = mid. Please note that arr[mid] can also be the largest element.
{50, 10, 20, 30, 40}, mid = (0 + 4)/2 = 2. arr[2] is 20. If arr[mid] is smaller than or equal to arr[lo], then we go to the left half.
How do we terminate the search? One way could be to check if the mid is smaller than both of its adjacent, then we return mid. This would require a lot of condition checks like if adjacent indexes are valid or not and then comparing mid with both. We use an interesting fact here. If arr[lo] <= arr[hi], then the current subarray must be sorted, So we return arr[hi]. This optimizes the code drastically as we do not have to explicitly check the whole sorted array.