3 of 5
Write a function first_occurrence(nums, target) that returns the leftmost index of target in a sorted list that may contain duplicates.
Return -1 if target is not in the list.
print(first_occurrence([1, 2, 2, 2, 3, 4], 2)) # 1 print(first_occurrence([1, 2, 2, 2, 3, 4], 3)) # 4 print(first_occurrence([1, 2, 2, 2, 3, 4], 5)) # -1 print(first_occurrence([2, 2, 2, 2, 2], 2)) # 0
| Complexity | |
|---|---|
| Time | O(log n) |
| Space | O(1) |
Standard binary search finds a match — but not necessarily the leftmost one. The trick is to keep searching left even after you find a match:
lo = 0, hi = len(nums) - 1, result = -1lo <= hi:
mid = (lo + hi) // 2nums[mid] == target → record result = mid, then set hi = mid - 1 to look further leftnums[mid] < target → set lo = mid + 1nums[mid] > target → set hi = mid - 1resultdef first_occurrence(nums, target): pass print(first_occurrence([1, 2, 2, 2, 3, 4], 2)) # 1 print(first_occurrence([1, 2, 2, 2, 3, 4], 3)) # 4 print(first_occurrence([1, 2, 2, 2, 3, 4], 5)) # -1 print(first_occurrence([2, 2, 2, 2, 2], 2)) # 0