Upper Bound and Count

Step 3 β€” Upper Bound and Count

lower_bound found the first element that is at least target. upper_bound is its twin: it returns the index of the first element strictly greater than target. Together they bracket every copy of a value, which is exactly how you answer "how many times does this appear?" in one logarithmic sweep.

Implement two functions:

  • upper_bound(arr, target): same half-open search as lower_bound, but move lo up while arr[mid] <= target (note the <=). It returns the index just past the last occurrence.
  • count(arr, target): return upper_bound(arr, target) - lower_bound(arr, target). The half-open span between the two bounds is the number of matches, and it is naturally 0 when the value is absent.

Reuse the lower_bound you wrote in the previous step.

Hints
Starter code
def search(arr, target):
    lo, hi = 0, len(arr) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1


def lower_bound(arr, target):
    lo, hi = 0, len(arr)
    while lo < hi:
        mid = (lo + hi) // 2
        if arr[mid] < target:
            lo = mid + 1
        else:
            hi = mid
    return lo


def upper_bound(arr, target):
    """Return the index of the first element > target, or len(arr)."""
    # TODO: like lower_bound but move lo past elements <= target.
    pass


def count(arr, target):
    """Return how many times target occurs, via upper_bound - lower_bound."""
    # TODO: return upper_bound(arr, target) - lower_bound(arr, target).
    pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.