An interactive visualization of how two binary searches find the leftmost and rightmost positions of a target in a sorted array. Watch each phase narrow down the search space step by step.
Binary Search LeetCode 34 โ Mediumnums sorted in non-decreasing order, find the starting and ending position of a given target value.target is not found in the array, return [-1, -1].fun searchRange(nums: IntArray, target: Int): IntArray { fun findLeft(nums: IntArray, target: Int): Int { var lo = 0; var hi = nums.size - 1 var idx = -1 while (lo <= hi) { val mid = (lo + hi) / 2 if (nums[mid] == target) { idx = mid hi = mid - 1 // keep searching left } else if (nums[mid] < target) { lo = mid + 1 } else { hi = mid - 1 } } return idx } fun findRight(nums: IntArray, target: Int): Int { var lo = 0; var hi = nums.size - 1 var idx = -1 while (lo <= hi) { val mid = (lo + hi) / 2 if (nums[mid] == target) { idx = mid lo = mid + 1 // keep searching right } else if (nums[mid] < target) { lo = mid + 1 } else { hi = mid - 1 } } return idx } return intArrayOf(findLeft(nums, target), findRight(nums, target))}
A standard binary search finds any occurrence of the target, but we need the first and last positions. The trick is to run two modified binary searches: one that keeps searching left after finding the target (to find the leftmost occurrence), and one that keeps searching right (to find the rightmost occurrence).
nums[mid] == target, record mid as a candidate and set hi = mid - 1 to continue searching in the left half for an earlier occurrence.nums[mid] == target, record mid as a candidate and set lo = mid + 1 to continue searching in the right half for a later occurrence.nums[mid] < target, move lo = mid + 1. If nums[mid] > target, move hi = mid - 1.-1 if the target was never found.
Two binary searches each run in O(log n), so the total time is O(log n).
Only a constant number of variables are used, giving O(1) space.