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.

  • Merge Intervals:
    Given a collection of intervals, merge all overlapping intervals.

  • Insert Interval:
    Insert a new interval into a list of non-overlapping intervals and merge if necessary.

  • Calendar Problems (e.g., My Calendar):
    Problems that involve booking intervals and checking for overlaps.

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
What is manipulator in C++?
Which software is used by network engineer?
Reset local repository branch to be just like remote repository HEAD
Related Courses
Image
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.
Image
Grokking Modern AI Fundamentals
Master the fundamentals of AI today to lead the tech revolution of tomorrow.
Image
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.
;