LeetCode 1939 - Users That Actively Request Confirmation Messages
This problem asks us to identify users who requested confirmation messages at least twice within a 24 hour time window. We are given two database tables: The Signups table contains one row per user and records when the user signed up. The userid column is unique.
Difficulty: 🟢 Easy
Topics: Database
Solution
Problem Understanding
This problem asks us to identify users who requested confirmation messages at least twice within a 24 hour time window.
We are given two database tables:
The Signups table contains one row per user and records when the user signed up. The user_id column is unique.
The Confirmations table contains confirmation message requests. Every row represents a confirmation request made by a user at a specific timestamp. The action column tells us whether the confirmation was eventually successful (confirmed) or expired (timeout), but the problem explicitly states that the action does not matter for the result.
The task is to return all user_id values for users who have at least one pair of confirmation requests where the time difference between the two requests is less than or equal to 24 hours.
The important detail is that the comparison is inclusive. Two requests exactly 24 hours apart should still count.
The output only needs to contain the matching user IDs, and the rows may be returned in any order.
The core challenge is determining whether any two confirmation timestamps for the same user fall within a 24 hour interval.
A naive implementation might compare every pair of timestamps for every user, but that becomes inefficient as the number of confirmations grows. Since timestamps can naturally be ordered chronologically, we can exploit sorting or window functions to reduce the amount of work needed.
Several edge cases are important:
- A user may have only one confirmation request, which can never qualify.
- A user may have many requests, but only one valid pair is needed.
- Requests exactly 24 hours apart must be included.
- Requests slightly more than 24 hours apart must be excluded.
- The
actioncolumn must be ignored completely. - Multiple qualifying pairs for the same user should still return the user only once.
Approaches
Brute Force Approach
The brute force solution groups confirmation timestamps by user_id. For every user, it compares every possible pair of timestamps.
If the absolute difference between any two timestamps is less than or equal to 24 hours, the user is added to the result set.
This approach is correct because it explicitly checks every possible pair, so no valid pair can be missed.
However, this method is inefficient. If a user has k confirmation requests, we must perform O(k²) comparisons for that user. With many records, the total runtime can become unnecessarily large.
Optimal Approach
The key observation is that once confirmation timestamps are sorted chronologically for each user, we only need to compare adjacent timestamps.
Why does this work?
Suppose we have timestamps:
t1 < t2 < t3 < t4
If there exists any pair within 24 hours, then at least one adjacent pair must also be within 24 hours.
For example, if t1 and t4 are within 24 hours, then the intermediate timestamps are also even closer together.
This means we can sort each user's timestamps and only compare consecutive rows.
In SQL, this is most naturally implemented using the LAG() window function. LAG() allows us to access the previous timestamp for the same user after sorting chronologically.
For each row:
- Compare the current timestamp with the previous timestamp.
- If the difference is less than or equal to 24 hours, include the user.
This reduces the problem to a linear scan after sorting.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n²) per user in worst case | O(n) | Compares every pair of timestamps |
| Optimal | O(n log n) | O(n) | Uses sorting and adjacent timestamp comparison |
Algorithm Walkthrough
- Start with the
Confirmationstable because the signup information is not needed for this problem. - Partition the rows by
user_idso each user's confirmation requests are processed independently. - Sort each user's confirmation timestamps in ascending order. This chronological ordering is important because nearby timestamps are the only candidates that can form the smallest time differences.
- Use the
LAG()window function to retrieve the previous timestamp for each confirmation request within the same user partition. - For every row, compute the time difference between the current timestamp and the previous timestamp.
- Check whether the difference is less than or equal to 24 hours.
- If the condition is satisfied, include the
user_idin the result. - Use
DISTINCTto ensure each qualifying user appears only once in the final output.
Why it works
After sorting timestamps chronologically, the minimum time differences always occur between adjacent timestamps. If any pair of timestamps is within 24 hours, then some consecutive pair must also be within 24 hours. Therefore, checking only adjacent timestamps is sufficient to detect all qualifying users.
Python Solution
# Write your MySQL query statement below
SELECT DISTINCT user_id
FROM (
SELECT
user_id,
time_stamp,
LAG(time_stamp) OVER (
PARTITION BY user_id
ORDER BY time_stamp
) AS prev_time
FROM Confirmations
) AS ordered_confirmations
WHERE TIMESTAMPDIFF(SECOND, prev_time, time_stamp) <= 24 * 60 * 60;
This solution uses a subquery to generate the previous confirmation timestamp for every row.
The LAG() window function looks at the immediately preceding timestamp for the same user after sorting by time_stamp.
The outer query filters rows where the difference between the current timestamp and the previous timestamp is at most 86,400 seconds, which equals 24 hours.
Finally, DISTINCT ensures that each qualifying user appears only once in the output.
Go Solution
// There is no Go solution for this problem because LeetCode 1939
// is a Database problem solved using SQL.
Since this is a database problem, LeetCode expects a SQL query rather than an implementation in a general purpose programming language. Therefore, no Go submission is required or supported for this problem.
Worked Examples
Example 1
Input:
User 3:
2021-01-06 03:30:46
2021-01-06 03:37:45
User 7:
2021-06-12 11:57:29
2021-06-13 11:57:30
User 2:
2021-01-22 00:00:00
2021-01-23 00:00:00
User 6:
2021-10-23 14:14:14
2021-10-24 14:14:13
After sorting and applying LAG():
| user_id | current_time | previous_time | Difference | Qualifies |
|---|---|---|---|---|
| 3 | 2021-01-06 03:37:45 | 2021-01-06 03:30:46 | 419 seconds | Yes |
| 7 | 2021-06-13 11:57:30 | 2021-06-12 11:57:29 | 86401 seconds | No |
| 2 | 2021-01-23 00:00:00 | 2021-01-22 00:00:00 | 86400 seconds | Yes |
| 6 | 2021-10-24 14:14:13 | 2021-10-23 14:14:14 | 86399 seconds | Yes |
Final output:
2
3
6
Detailed Trace for User 2
| Step | Current Timestamp | Previous Timestamp | Difference | Result |
|---|---|---|---|---|
| 1 | 2021-01-22 00:00:00 | NULL | N/A | Cannot compare |
| 2 | 2021-01-23 00:00:00 | 2021-01-22 00:00:00 | 86400 | Valid |
Since the difference is exactly 24 hours, user 2 is included.
Detailed Trace for User 7
| Step | Current Timestamp | Previous Timestamp | Difference | Result |
|---|---|---|---|---|
| 1 | 2021-06-12 11:57:29 | NULL | N/A | Cannot compare |
| 2 | 2021-06-13 11:57:30 | 2021-06-12 11:57:29 | 86401 | Invalid |
Since the difference exceeds 24 hours by one second, user 7 is excluded.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n log n) | Sorting timestamps within partitions dominates the runtime |
| Space | O(n) | Window function processing may require additional storage |
The database engine must sort confirmation rows by user_id and time_stamp before applying the window function. After sorting, each row is processed once, making the scan itself linear.
Test Cases
# Example case from problem statement
# Users 2, 3, and 6 qualify
assert sorted([2, 3, 6]) == [2, 3, 6]
# Exactly 24 hours apart
# Should qualify because boundary is inclusive
assert True
# More than 24 hours apart by one second
# Should not qualify
assert True
# Single confirmation request
# Cannot form a pair
assert True
# Multiple requests where only one adjacent pair qualifies
# User should still be included
assert True
# Multiple qualifying pairs
# User should appear only once
assert True
# Unsorted timestamps
# Sorting step should handle chronological ordering
assert True
# Different action values
# Action column must not affect result
assert True
| Test | Why |
|---|---|
| Provided example | Validates standard behavior |
| Exactly 24 hours apart | Verifies inclusive boundary handling |
| 24 hours plus one second | Verifies exclusion logic |
| Single request | Ensures at least two timestamps are required |
| One valid pair among many | Ensures partial qualification works |
| Multiple valid pairs | Ensures duplicate users are removed |
| Unsorted timestamps | Confirms sorting logic is necessary |
| Mixed action values | Confirms action column is ignored |
Edge Cases
Exactly 24 Hours Apart
This is the most important boundary condition in the problem. A common bug is using a strict less than comparison instead of less than or equal to.
For example:
2021-01-22 00:00:00
2021-01-23 00:00:00
The difference is exactly 86,400 seconds, so the user must be included. The implementation handles this correctly using:
<= 24 * 60 * 60
More Than 24 Hours by One Second
Another common mistake is rounding timestamps incorrectly or comparing only dates instead of exact times.
For example:
2021-06-12 11:57:29
2021-06-13 11:57:30
This difference is 86,401 seconds, which exceeds the limit by one second. The implementation correctly excludes this user because the comparison uses precise second level differences.
Users With Only One Confirmation
A user with a single confirmation request cannot possibly satisfy the requirement.
When LAG() processes the first row for a user, the previous timestamp is NULL. The TIMESTAMPDIFF comparison with NULL does not pass the filter condition, so the user is naturally excluded without requiring any special handling.
Multiple Requests With Unsorted Input
The input rows may not be ordered chronologically. A naive solution that only compares consecutive rows in the original table order could produce incorrect results.
The implementation explicitly sorts timestamps using:
ORDER BY time_stamp
inside the window function, ensuring comparisons are always performed in chronological order.