715. Range Module - Detailed Explanation

Free Coding Questions Catalog
Boost your coding skills with our essential coding questions catalog. Take a step towards a better tech career now!

Problem Statement

You are asked to design a data structure that tracks ranges of numbers (represented as half‐open intervals [left, right)) and supports the following operations:

  • addRange(left, right):
    Adds the half-open interval [left, right) to the module. After adding, any number within that interval should be considered “covered.” Overlapping or adjacent intervals should be merged.

  • queryRange(left, right):
    Returns true if every number in the half-open interval [left, right) is currently covered by some added range(s); otherwise, returns false.

  • removeRange(left, right):
    Removes all numbers in the half-open interval [left, right) from the module. This operation may partially cut through an existing interval, splitting it into two intervals if needed.

Constraints:

  • The number of operations can be large (e.g., up to 10⁴).
  • The range of the numbers (left and right values) can be up to 10⁹.
  • It is important to implement the operations efficiently.

Example:

RangeModule rm = new RangeModule();
rm.addRange(10, 20);       // Adds the interval [10, 20)
rm.removeRange(14, 16);    // Removes the interval [14, 16), resulting in intervals [10, 14) and [16, 20)
rm.queryRange(10, 14);     // Returns true because [10, 14) is fully covered.
rm.queryRange(13, 15);     // Returns false because 14 is not covered.
rm.queryRange(16, 17);     // Returns true because [16, 17) is covered.

Hints

  • Hint 1: Think about how to maintain a set of disjoint intervals that represent the union of all added ranges. This will help in merging overlapping intervals when adding and in efficiently checking coverage during queries.
  • Hint 2: When performing operations (add or remove), you may need to find the correct insertion point quickly. Consider using binary search on a sorted list of intervals.
  • Hint 3: For queries, all you need to do is check if there is an interval that completely covers the given range.

Approaches

There are two common strategies to implement a Range Module:

Idea:
Maintain a sorted list (or array) of disjoint intervals. Each interval is represented as [start, end).

  • addRange: Use binary search to find intervals overlapping with [left, right), merge them, and update the list.
  • queryRange: Use binary search to locate the interval whose start is just before or equal to the query’s left, then check if that interval’s end is at least right.
  • removeRange: Similar to addRange; find all intervals that overlap with [left, right) and adjust or split them as needed.

Why It Works:
By keeping the intervals disjoint and sorted, each operation can run efficiently by scanning only the intervals that are relevant to the current operation.

Idea:
Use a BST (or Java’s TreeMap) keyed by the start of the intervals. The BST allows you to quickly find the closest interval for a given query and to update intervals during add and remove operations.

Why It Works:
This data structure efficiently supports insertion, deletion, and querying in logarithmic time. Many languages offer built-in trees or sorted maps that make this approach straightforward.

Python Code

Below is a Python implementation using a sorted list of intervals with binary search.

Python3
Python3

. . . .

Java Code

Below is the Java implementation using a TreeMap to manage intervals.

Java
Java

. . . .

Complexity Analysis

  • Time Complexity:
    • addRange / removeRange:
      With a sorted list approach, each operation may scan through several intervals. In the worst-case (merging or splitting many intervals), the time can be O(k) where k is the number of overlapping intervals. Using a TreeMap (or balanced BST), each operation (search, insertion, deletion) is O(log n) per individual update, with extra cost if multiple intervals are merged.

    • queryRange:
      O(log n) when using binary search or a TreeMap lookup.

  • Space Complexity:
    • O(n) for storing the intervals. In the worst-case, every interval is disjoint.

Step-by-Step Walkthrough & Visual Example

Consider the following operations:

  1. Operation: addRange(10, 20)

    • Since there are no existing intervals, add [10, 20).
    • Intervals: [[10, 20)] (or TreeMap: {10=20})
  2. Operation: removeRange(14, 16)

    • The current interval [10, 20) overlaps with [14, 16).
    • Split [10, 20) into two intervals:
      • [10, 14) (before 14) and [16, 20) (after 16).
    • Intervals: [[10, 14), [16, 20)]
  3. Operation: queryRange(10, 14)

    • Check if there is an interval covering [10, 14).
    • The interval [10, 14) exactly covers the query, so return true.
  4. Operation: queryRange(13, 15)

    • Although 13–14 is covered by [10, 14), the segment [14, 15) is missing because of the removal.
    • Return false.
  5. Operation: queryRange(16, 17)

    • The interval [16, 20) covers [16, 17), so return true.

A visual representation after each step helps understand how intervals are merged and split.

Common Mistakes, Edge Cases & Alternative Variations

Common Mistakes:

  • Merging Intervals Incorrectly:
    Failing to merge overlapping intervals during addRange can lead to gaps or duplicate intervals.
  • Off-by-One Errors:
    Remember that the intervals are half-open [left, right); it means the right endpoint is not included.
  • Improper Splitting:
    When removing ranges, it’s common to forget to split an interval into two when the removal interval is in the middle.

Edge Cases:

  • Adding or Removing a Range that Doesn’t Overlap:
    Ensure the data structure correctly handles non-overlapping intervals.

  • Queries on Empty Range:
    Querying a range when no intervals exist should return false.

  • Boundary Conditions:
    Adding ranges that touch (e.g., [10, 15) and [15, 20)) should be merged into [10, 20).

Alternative Variations:

  • Segment Trees:
    For more dynamic range queries and updates, a segment tree can be used, though it is more complex to implement.

  • Interval Trees:
    These trees are designed for storing intervals and quickly finding all intervals that overlap with a given query.

TAGS
leetcode
CONTRIBUTOR
Design Gurus Team
-

GET YOUR FREE

Coding Questions Catalog

Design Gurus Newsletter - Latest from our Blog
Boost your coding skills with our essential coding questions catalog.
Take a step towards a better tech career now!
Explore Answers
Related Courses
Grokking the Coding Interview: Patterns for Coding Questions
Grokking the Coding Interview Patterns in Java, Python, JS, C++, C#, and Go. The most comprehensive course with 476 Lessons.
Grokking Modern AI Fundamentals
Master the fundamentals of AI today to lead the tech revolution of tomorrow.
Grokking Data Structures & Algorithms for Coding Interviews
Unlock Coding Interview Success: Dive Deep into Data Structures and Algorithms.
Image
One-Stop Portal For Tech Interviews.
Copyright © 2025 Design Gurus, LLC. All rights reserved.
;