mediumBinary SearchPattern: Binary Search
Find Closest Element in Sorted Array Solution
Problem Statement
Given a strictly increasing array of integers `arr` and an integer `target`, find the index of the element in `arr` that is closest to `target`. If there are multiple elements equally close, return the index of the smaller element.
Examples
Example 1:
Input:{"arr":[1,3,5,7,9],"target":6}
Output:2
Explanation: The elements are 1, 3, 5, 7, 9. The target is 6. The differences are |1-6|=5, |3-6|=3, |5-6|=1, |7-6|=1, |9-6|=3. The minimum difference is 1, achieved by elements 5 (at index 2) and 7 (at index 3). Since the problem asks for the index of the element with the smaller value in case of ties, we return the index of 5, which is 2.
Constraints
- 1 <= arr.length <= 10^5
- -10^9 <= arr[i] <= 10^9
- arr is strictly increasing.
- -10^9 <= target <= 10^9
Time: O(log n) Space: O(1)
Use binary search to efficiently narrow down the search space. During the binary search, continuously update the closest element found so far. After the binary search loop finishes, compare the elements at the final `left` and `right` pointers (or adjacent indices) to determine the absolute closest element, handling ties by selecting the smaller index.
Run, Test & Submit Code
Ready to practice this challenge? Launch our interactive compilation environment with compiler validation.
Solve on Interactive WorkspaceTested Solutions
import math
def find_closest_element_in_sorted_array(arr, target):
if not arr:
return -1
left, right = 0, len(arr) - 1
closest_index = 0
while left <= right:
mid = left + (right - left) // 2
diff_mid = abs(arr[mid] - target)
diff_closest = abs(arr[closest_index] - target)
if diff_mid < diff_closest:
closest_index = mid
elif diff_mid == diff_closest:
closest_index = min(closest_index, mid)
if arr[mid] < target:
left = mid + 1
elif arr[mid] > target:
right = mid - 1
else:
return mid # Exact match is the closest
# After the loop, the 'left' pointer will be at the first element greater than target
# and 'right' will be at the first element smaller than target.
# We need to check these two potential candidates.
# Check the element at 'left' if it's within bounds
if left < len(arr):
diff_left = abs(arr[left] - target)
diff_closest = abs(arr[closest_index] - target)
if diff_left < diff_closest:
closest_index = left
elif diff_left == diff_closest:
closest_index = min(closest_index, left)
# Check the element at 'right' if it's within bounds
if right >= 0:
diff_right = abs(arr[right] - target)
diff_closest = abs(arr[closest_index] - target)
if diff_right < diff_closest:
closest_index = right
elif diff_right == diff_closest:
closest_index = min(closest_index, right)
return closest_index