Prerequisites

Before attempting this problem, you should be comfortable with:

  • Array Traversal - Iterating through a sorted array while comparing consecutive elements to detect gaps
  • Interval Representation - Understanding how to construct and return ranges as pairs of start and end values
  • Edge Case Handling - Managing boundary conditions such as empty arrays, gaps before the first element, and gaps after the last element

1. Linear Scan

Intuition

We need to identify all gaps in the range [lower, upper] that are not covered by the sorted array nums. There are three places where gaps can occur: before the first element, between consecutive elements, and after the last element. By checking each of these locations, we can collect all missing ranges in a single pass.

Algorithm

  1. If the array is empty, the entire range [lower, upper] is missing. Return it as a single range.
  2. Check if there is a gap between lower and nums[0]. If lower < nums[0], add [lower, nums[0] - 1] to the result.
  3. Iterate through consecutive pairs in the array. For each pair (nums[i], nums[i + 1]):
    • If the difference is greater than 1, there is a gap. Add [nums[i] + 1, nums[i + 1] - 1] to the result.
  4. Check if there is a gap between nums[n - 1] and upper. If upper > nums[n - 1], add [nums[n - 1] + 1, upper] to the result.
  5. Return the list of missing ranges.
class Solution:
    def findMissingRanges(
        self, nums: List[int], lower: int, upper: int
    ) -> List[List[int]]:
        n = len(nums)
        missing_ranges = []
        if n == 0:
            missing_ranges.append([lower, upper])
            return missing_ranges

        # Check for any missing numbers between the lower bound and nums[0].
        if lower < nums[0]:
            missing_ranges.append([lower, nums[0] - 1])

        # Check for any missing numbers between successive elements of nums.
        for i in range(n - 1):
            if nums[i + 1] - nums[i] <= 1:
                continue
            missing_ranges.append([nums[i] + 1, nums[i + 1] - 1])

        # Check for any missing numbers between the last element of nums and the upper bound.
        if upper > nums[n - 1]:
            missing_ranges.append([nums[n - 1] + 1, upper])

        return missing_ranges

Time & Space Complexity

  • Time complexity: O(n)O(n)
  • Space complexity: O(1)O(1) constant space

Where nn is the number of elements in nums.

Common Pitfalls

Forgetting the Empty Array Case

When nums is empty, the entire range [lower, upper] is missing. Failing to handle this edge case before iterating through the array leads to index out-of-bounds errors or incorrect results. Always check for an empty array first and return [lower, upper] as the single missing range.

Off-by-One Errors in Range Boundaries

A common mistake is using incorrect boundary calculations when constructing missing ranges. For gaps before the first element, the range should be [lower, nums[0] - 1], not [lower, nums[0]]. Similarly, for gaps between consecutive elements, the range is [nums[i] + 1, nums[i + 1] - 1]. Using <= instead of < in comparisons or forgetting to add/subtract 1 from boundaries results in including existing elements or missing valid gaps.