We use cookies (including Google cookies) to personalize ads and analyze traffic. By continuing to use our site, you accept our Privacy Policy.

Custom Interval

Number: 2908

Difficulty: Medium

Paid? Yes

Companies: N/A


Problem Description

Implement two functions: customInterval and customClearInterval. customInterval takes a function fn, a delay, and a period and repeatedly executes fn with intervals defined by the formula (delay + period * count), where count starts at 0 for the first call. customClearInterval stops any further executions when provided with the id returned from customInterval.


Key Insights

  • Instead of using setInterval, use recursive scheduling with setTimeout (or equivalent in other languages).
  • The delay for each execution increases linearly using the formula delay + period * count.
  • Maintain a cancellation flag or reference so that scheduled future calls can be terminated.

Space and Time Complexity

Time Complexity: O(n) for n executions, where each timer callback runs in constant time. Space Complexity: O(1) additional space is needed for the cancellation flag and timer reference.


Solution

To solve the problem, we use a recursive scheduling method. In JavaScript, for example, we use setTimeout to schedule the next execution. On each execution, we first check if a cancellation flag is set; if not, we execute the provided function fn, increment the count, compute the next delay based on the formula, and then recursively schedule the next call. For cancellation with customClearInterval, we update the flag and clear the current timeout if necessary. Similar ideas can be applied in other languages using available timer/scheduling mechanisms, ensuring that each scheduled execution can be cancelled when needed.


Code Solutions

import threading

def customInterval(fn, delay, period):
    # intervalObj will hold the state for cancellation and timer reference.
    state = {"cancelled": False, "count": 0, "timer": None}

    def schedule():
        # Compute the delay for the current execution
        current_delay = delay + period * state["count"] / 1000.0  # convert ms to seconds for Timer
        # Create a Timer to call the function
        state["timer"] = threading.Timer(current_delay, run)
        state["timer"].start()
    
    def run():
        if state["cancelled"]:
            return
        fn()
        state["count"] += 1
        schedule()
    
    schedule()
    return state

def customClearInterval(interval_state):
    interval_state["cancelled"] = True
    timer = interval_state.get("timer")
    if timer is not None:
        timer.cancel()

# Example usage:
if __name__ == "__main__":
    import time
    start = time.perf_counter()
    results = []
    def fn():
        results.append(int((time.perf_counter() - start)*1000))
        print("Called at", results[-1], "ms")
    state = customInterval(fn, 50, 20)
    # Cancel after 225 ms
    threading.Timer(0.225, lambda: customClearInterval(state)).start()
    time.sleep(0.5)  # Wait long enough to capture scheduled calls
    print(results)
← Back to All Questions