The Problem

Given an array of integers nums sorted in non-decreasing 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.

Interactive Visualization

Speed:
Array
Current Step
Press Step or Play to begin.
Code
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))}

How It Works

Key Insight

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).

The Algorithm

  • Phase 1 โ€” findLeft: When nums[mid] == target, record mid as a candidate and set hi = mid - 1 to continue searching in the left half for an earlier occurrence.
  • Phase 2 โ€” findRight: When nums[mid] == target, record mid as a candidate and set lo = mid + 1 to continue searching in the right half for a later occurrence.
  • In both phases, if nums[mid] < target, move lo = mid + 1. If nums[mid] > target, move hi = mid - 1.
  • Each phase returns the last recorded candidate index, or -1 if the target was never found.

Complexity

Time O(log n)
Space O(1)

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.