Find motion intervals above threshold
Company: Verkada
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of time-series data processing and interval detection, focusing on grouping timestamped motion readings that exceed a numeric threshold and managing contiguous active segments.
Find motion intervals above threshold
Constraints
- readings is sorted by time in strictly increasing order
- 0 <= len(readings) (the list may be empty)
- time is an integer; motion_level and T are real numbers
- A reading equal to the threshold (motion_level == T) is treated as active
Examples
Input: ([[1, 0.4], [5, 0.2], [11, 0.9], [15, 0.9], [17, 0.8], [25, 0.5], [27, 0.8], [36, 0.9]], 0.8)
Expected Output: [[11, 17], [27, 36]]
Explanation: Times 11,15,17 are >= 0.8 -> [11,17]; times 27,36 are >= 0.8 -> [27,36]; everything else is below threshold.
Input: ([], 0.5)
Expected Output: []
Explanation: Empty input yields no intervals.
Input: ([[3, 0.9]], 0.5)
Expected Output: [[3, 3]]
Explanation: A single active reading is a degenerate interval [3,3].
Input: ([[1, 0.2], [2, 0.3], [3, 0.1]], 0.5)
Expected Output: []
Explanation: No reading reaches the threshold.
Input: ([[1, 0.9], [2, 0.9], [3, 0.9]], 0.5)
Expected Output: [[1, 3]]
Explanation: All three readings are active and contiguous -> one interval spanning first to last time.
Input: ([[1, 0.6], [2, 0.7], [3, 0.4], [4, 0.7], [5, 0.7]], 0.5)
Expected Output: [[1, 2], [4, 5]]
Explanation: An inactive reading at time 3 splits the active readings into two runs.
Input: ([[10, -0.5], [20, -0.2], [30, -0.8]], -0.3)
Expected Output: [[20, 20]]
Explanation: Negative thresholds work the same way: only -0.2 >= -0.3 is active.
Input: ([[1, 0.8], [2, 0.5], [3, 0.8]], 0.8)
Expected Output: [[1, 1], [3, 3]]
Explanation: Readings exactly equal to the threshold (0.8 at T=0.8) count as active; the inactive 0.5 between them splits them into two single-point intervals.
Hints
- Make a single left-to-right pass, tracking whether you are currently inside an active run.
- Open a run on the first active reading; the run's start_time is that reading's time. Keep updating the run's end_time to the latest active reading's time.
- Close (emit) the run the moment you hit an inactive reading, and remember to emit any run still open when the loop ends.
Time intervals where all cameras are active
Constraints
- Each camera's readings are sorted by strictly increasing time
- cameras may be empty (return [])
- Thresholding is inclusive: motion_level == T counts as active
- Intervals are closed [start_time, end_time]; an intersection is non-empty when start <= end
Examples
Input: ([[[1, 0.4], [5, 0.2], [11, 0.9], [15, 0.9], [17, 0.8], [25, 0.5], [27, 0.8], [36, 0.9]]], 0.8)
Expected Output: [[11, 17], [27, 36]]
Explanation: A single camera reduces to Part 1: its own active intervals.
Input: ([[[1, 0.9], [2, 0.9], [3, 0.2], [4, 0.9]], [[1, 0.2], [2, 0.9], [3, 0.9], [4, 0.9]]], 0.8)
Expected Output: [[2, 2], [4, 4]]
Explanation: Cam0 active [[1,2],[4,4]], Cam1 active [[2,4]]; overlaps are [2,2] and [4,4].
Input: ([[[1, 0.9], [2, 0.9], [3, 0.9]], [[1, 0.9], [2, 0.9], [3, 0.9]]], 0.5)
Expected Output: [[1, 3]]
Explanation: Both cameras active over the whole span -> full overlap [1,3].
Input: ([[[1, 0.9], [2, 0.9]], [[1, 0.1], [2, 0.1]]], 0.5)
Expected Output: []
Explanation: The second camera is never active, so there is no common active time.
Input: ([], 0.5)
Expected Output: []
Explanation: No cameras -> empty result.
Input: ([[[1, 0.9], [5, 0.9], [9, 0.9]]], 0.5)
Expected Output: [[1, 9]]
Explanation: One camera, all active and contiguous -> [1,9] (time gaps inside an active run are kept).
Input: ([[[1, 0.9], [3, 0.9], [5, 0.2], [7, 0.9], [9, 0.9]], [[1, 0.2], [3, 0.9], [5, 0.9], [7, 0.9], [9, 0.2]]], 0.5)
Expected Output: [[3, 3], [7, 7]]
Explanation: Cam0 active [[1,3],[7,9]], Cam1 active [[3,7]]; intersecting gives [3,3] and [7,7].
Hints
- Reuse Part 1: turn each camera into its own list of active intervals first.
- To intersect two sorted, non-overlapping interval lists, walk both with two pointers; the overlap of [a1,b1] and [a2,b2] is [max(a1,a2), min(b1,b2)] and exists only when that low <= high.
- Fold the cameras one at a time: keep a running intersection and merge each new camera into it. If the running intersection ever becomes empty, you can stop early.