← Back to All Algorithms

Medium Interview Frequency: ⭐⭐⭐⭐

Find First And Last Position

Given a sorted array nums and a target, return the first and last index of target as [start, end]. If not found, return [-1, -1].

Binary Search Sorted Arrays

📚 Table of Contents

  1. Problem Statement
  2. Real-World Analogy
  3. Key Insights
  4. Solution Approaches
  5. Step-by-Step Walkthrough
  6. Complexity Analysis
  7. Edge Cases
  8. Test Cases
  9. Interview Tips
  10. Related Problems
  11. Key Takeaways

📋 Problem Statement

Array is sorted in non-decreasing order. Return the smallest and largest indices where nums[i] == target.

Examples

Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]

Constraints

🎯 Real-World Analogy

Finding First and Last Book on a Shelf

Books are sorted alphabetically. You want the first and last position of a title. One search finds the left boundary, another finds the right boundary.

Instead of scanning every book, jump to the middle repeatedly. Direction depends on whether middle is before or after boundary condition.

💡 Key Insights

💻 Solution Approaches

Approach 1: Linear Scan

Time: O(N) | Space: O(1)

Simple but violates logarithmic follow-up requirement.

Approach 2: Two Binary Searches (Recommended)

Time: O(log N) | Space: O(1)

Find the target interval boundaries directly.

Python Implementation

from typing import List def search_range(nums: List[int], target: int) -> List[int]: def first_ge(x: int) -> int: left, right = 0, len(nums) while left < right: mid = (left + right) // 2 if nums[mid] < x: left = mid + 1 else: right = mid return left left = first_ge(target) if left == len(nums) or nums[left] != target: return [-1, -1] right = first_ge(target + 1) - 1 return [left, right]

JavaScript Implementation

function searchRange(nums, target) { function firstGE(x) { let left = 0; let right = nums.length; while (left < right) { const mid = Math.floor((left + right) / 2); if (nums[mid] < x) { left = mid + 1; } else { right = mid; } } return left; } const left = firstGE(target); if (left === nums.length || nums[left] !== target) { return [-1, -1]; } const right = firstGE(target + 1) - 1; return [left, right]; }

🔍 Step-by-Step Walkthrough

Trace nums=[5,7,7,8,8,10], target=8:

first_ge(8) returns index 3 (first 8).
first_ge(9) returns index 5 (value 10).
Right boundary = 5 - 1 = 4. Answer = [3,4].

⚡ Complexity Analysis

Time Complexity: O(log N)

Space Complexity: O(1)

🔧 Edge Cases

🧪 Test Cases

Python

def test_search_range(): assert search_range([5,7,7,8,8,10], 8) == [3, 4] assert search_range([5,7,7,8,8,10], 6) == [-1, -1] assert search_range([], 1) == [-1, -1] assert search_range([2,2,2,2], 2) == [0, 3] assert search_range([1,3,5], 3) == [1, 1] print("✅ all tests passed")

JavaScript

function testSearchRange() { console.assert(JSON.stringify(searchRange([5,7,7,8,8,10], 8)) === JSON.stringify([3,4]), "test 1"); console.assert(JSON.stringify(searchRange([5,7,7,8,8,10], 6)) === JSON.stringify([-1,-1]), "test 2"); console.assert(JSON.stringify(searchRange([], 1)) === JSON.stringify([-1,-1]), "test 3"); console.log("✅ all tests passed"); }

💼 Interview Tips

🎓 Key Takeaways

← Back to All Algorithms