Solve Three Algorithmic Tasks
Company: Snapchat
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Onsite
Quick Answer: This set of three problems evaluates competencies in algorithm design and data structures, specifically efficient range counting on timestamped events, constrained selection/matching from double-sided cards, and merging multiple sorted lists.
Part 1: Count Events Inside Inclusive Time Windows
Constraints
- 0 <= len(events), len(queries) <= 200000
- Each timestamp is a valid time from '00:00:00' to '23:59:59'
- Event timestamps may be unsorted and may contain duplicates
- If a query has start_time > end_time, treat its answer as 0
Examples
Input: (['12:00:01', '01:02:02', '03:03:03'], [('01:02:01', '01:02:03'), ('01:00:00', '04:00:00')])
Expected Output: [1, 2]
Explanation: Only '01:02:02' is inside the first window. The second window includes '01:02:02' and '03:03:03'.
Input: (['00:00:00', '23:59:59', '12:30:30', '12:30:30'], [('12:30:30', '12:30:30'), ('00:00:00', '23:59:59'), ('13:00:00', '14:00:00')])
Expected Output: [2, 4, 0]
Explanation: The exact-time query counts both duplicates. The full-day query counts all events. The last window contains none.
Input: ([], [('00:00:00', '23:59:59')])
Expected Output: [0]
Explanation: There are no events, so every query returns 0.
Input: (['05:00:00'], [('05:00:00', '05:00:00'), ('06:00:00', '05:00:00')])
Expected Output: [1, 0]
Explanation: The first query matches the single event exactly. The second query has start_time > end_time, so its answer is 0.
Hints
- Convert each timestamp into seconds since midnight so comparisons become integer comparisons.
- After sorting the converted event times, use binary search to find how many values fall between the two endpoints.
Part 2: Form a Target String from Double-Sided Cards
Constraints
- 0 <= len(cards) <= 500
- 0 <= len(target) <= 500
- Each letter is a lowercase English letter
- A card like ['a', 'a'] can still be used at most once, so it contributes only one 'a'
Examples
Input: ([['a', 'b'], ['c', 'd']], 'ac')
Expected Output: True
Explanation: Use 'a' from the first card and 'c' from the second card.
Input: ([['a', 'b'], ['c', 'd']], 'ab')
Expected Output: False
Explanation: Both 'a' and 'b' are on the same card, but a card can be used only once.
Input: ([['a', 'a'], ['a', 'b'], ['c', 'd']], 'aac')
Expected Output: True
Explanation: Use the first card for one 'a', the second card for the other 'a', and the third card for 'c'.
Input: ([], '')
Expected Output: True
Explanation: An empty target needs no cards.
Input: ([], 'a')
Expected Output: False
Explanation: There are no cards available to supply any letter.
Hints
- Think of each needed target character as needing to be assigned to a distinct card that contains that letter.
- This can be solved as a bipartite matching problem between target positions and cards.
Part 3: Merge Multiple Sorted Lists
Constraints
- 0 <= len(lists) <= 100000
- 0 <= total number of integers across all lists <= 200000
- Each individual list is already sorted in non-decreasing order
- Values may be negative and duplicates are allowed
Examples
Input: ([[1, 4, 5], [1, 3, 4], [2, 6]])
Expected Output: [1, 1, 2, 3, 4, 4, 5, 6]
Explanation: Repeatedly taking the smallest front element across the lists produces the fully merged order.
Input: ([[], [0], [], [0, 2]])
Expected Output: [0, 0, 2]
Explanation: Empty inner lists should be ignored.
Input: ([])
Expected Output: []
Explanation: No lists means the merged result is empty.
Input: ([[-3, -1, 2], [-2, 2, 2], [5]])
Expected Output: [-3, -2, -1, 2, 2, 2, 5]
Explanation: Negative values and duplicates must remain in sorted order.
Input: ([[1]])
Expected Output: [1]
Explanation: A single one-element list is already merged.
Hints
- Keep track of the current smallest unused element from each list.
- A min-heap lets you repeatedly extract the next smallest value efficiently.