DSA Factory
Free Binary search lessonsBinary search · Stage 1 · First and last position · Step 3

The range of a value

Combine both searches into one answer, with one check for "not found." About 9 minutes.

Two searches, one answer

You already have both halves. One search finds where a value's block of copies starts, and the other finds where it ends. Call them back to back on the same x and you have the whole block: its range of positions.

It is like finding the first and last page of a chapter.

x is in the list? the first and last positions are its range.
x isn't there? The first search already returns minus one, so report minus one for both.
In code
def find(x, go_left):
    low, high, at = 0, len(nums) - 1, -1
    while low <= high:
        mid = (low + high) // 2
        if nums[mid] == x:
            at = mid
            if go_left:
                high = mid - 1
            else:
                low = mid + 1
        elif nums[mid] < x:
            low = mid + 1
        else:
            high = mid - 1
    return at

answers = []
for x in queries:
    first = find(x, True)
    if first == -1:
        answers.append([-1, -1])
    else:
        last = find(x, False)
        answers.append([first, last])
return answers
How many 3s, and where
1
0
3
1
3
2
3
3
6
4
8
5
8
6
firstlast

Search 1 (first occurrence): halving lands on index 1, the first 3.

Move 1 of 3

Don't run the second search for nothing

The two searches ask almost the same question, so if the first says x is missing, the second could only agree. Skipping it doesn't change the answer, it just saves the work.

In the code above, one helper leans left or right depending on a flag, so you don't write the loop twice.

First answer is minus one: means x is missing. There is nothing left to search for.
Quick check

nums = [5, 5, 5, 5, 9]. first_occurrence(5) is 0 and last_occurrence(5) is 3. What's the range for 5?

[5, 5, 5, 5, 9]
  1. A[0, 3]
  2. B[0, 4]
  3. C[-1, -1]
Show the answer

[0, 3]. That's exactly first_occurrence and last_occurrence, called and paired up — no extra work needed.

Your problem

The first and last position of a value

nums is sorted from smallest to largest and may have repeats. For each value in queries, return [first, last]: the first and last index where it appears in nums. If it never appears, return [-1, -1].

Example
nums = [2, 4, 4, 4, 4, 7, 9], queries = [4, 7, 2] → [[1, 4], [5, 5], [0, 0]]

0 ≤ n ≤ 2,000,000 · sorted ascending, may repeat · −1,000,000,000 ≤ every value ≤ 1,000,000,000 · up to 2,500 queries

Solve it in your browserFree account, no card. Python, C++, Java or JavaScript, with hints if you get stuck, and your progress is saved.
Sign up free to solve