1904. The Number of Full Rounds You Have Played
Problem Description
You're playing in an online chess tournament where rounds start every 15 minutes throughout the day. The first round begins at 00:00 (midnight), and subsequent rounds start at 00:15, 00:30, 00:45, 01:00, and so on.
You're given two time strings in 24-hour format:
loginTime
: when you log into the gamelogoutTime
: when you log out of the game
The task is to determine how many complete chess rounds you can play during your session.
Key points to understand:
- A round must be fully completed to count (you need to be logged in for the entire 15-minute duration)
- If
logoutTime
is earlier thanloginTime
(like logging in at 23:00 and logging out at 01:00), it means you played through midnight - Times are given in "HH:MM" format using the 24-hour clock
For example:
- If you login at 09:07 and logout at 09:30, you can play 1 full round (the 09:15-09:30 round)
- If you login at 09:07 and logout at 09:20, you can play 0 full rounds (you logged out before the 09:15 round ended)
The solution converts both times to minutes from midnight, handles the midnight wraparound case by adding 1440 minutes (24 hours) when needed, then calculates complete 15-minute intervals between the adjusted login time (rounded up to the next round start) and logout time (rounded down to the last round start).
Intuition
The key insight is to think about chess rounds as fixed time intervals on a timeline. Since rounds start at 00:00, 00:15, 00:30, etc., we can view them as intervals at positions 0, 15, 30, 45... minutes from midnight.
To count full rounds, we need to find which complete 15-minute intervals fall entirely within our login-logout window. This naturally leads us to think about:
- When is the first round we can fully participate in? (The first round that starts after we login)
- When is the last round we can fully complete? (The last round that ends before we logout)
Working with time strings directly is cumbersome, so converting everything to minutes from midnight simplifies calculations. This gives us a linear number line where rounds occur at multiples of 15.
The midnight wraparound initially seems tricky, but we can handle it elegantly by extending our timeline. If someone logs in at 23:00 and logs out at 01:00, instead of dealing with the wraparound logic repeatedly, we can treat the logout time as 01:00 + 24:00 = 25:00
(or 1500 minutes from the original midnight). This transforms the problem into a simple interval on a straight line.
For counting complete rounds:
- We need to find the first round starting at or after login: this is
(loginMinutes + 14) // 15
(adding 14 before dividing by 15 effectively rounds up to the next multiple of 15) - We need to find the last round ending at or before logout: this is
logoutMinutes // 15
(integer division rounds down to the previous multiple of 15) - The difference gives us the number of complete rounds
The max(0, b - a)
ensures we don't return negative values when someone logs in and out so quickly that they can't complete even one round.
Learn more about Math patterns.
Solution Approach
The implementation follows a straightforward conversion and calculation approach:
Step 1: Convert time strings to minutes
We define a helper function f(s)
that converts a time string "HH:MM" to total minutes from midnight:
- Extract hours:
int(s[:2])
- Extract minutes:
int(s[3:])
- Total minutes =
hours * 60 + minutes
For example, "09:30" becomes 9 * 60 + 30 = 570
minutes.
Step 2: Handle midnight wraparound
After converting both loginTime
and logoutTime
to minutes (a
and b
respectively), we check if a > b
. If true, it means the session crosses midnight, so we add 1440 minutes (24 hours) to b
:
if a > b: b += 1440
This transforms a wraparound case like login at 23:00 (1380 minutes) and logout at 01:00 (60 minutes) into a linear interval from 1380 to 1500 minutes.
Step 3: Find the round boundaries
We need to adjust our login and logout times to align with round boundaries:
- Round up login time to the next round start:
a = (a + 14) // 15
- Adding 14 before integer division by 15 effectively rounds up to the next multiple of 15
- This gives us the index of the first complete round we can play
- Round down logout time to the previous round start:
b = b // 15
- Simple integer division rounds down to the previous multiple of 15
- This gives us the index of the last complete round we can finish
Step 4: Calculate the number of complete rounds
The difference b - a
gives us the number of complete rounds. We use max(0, b - a)
to ensure we never return a negative value (which would happen if someone logs out before completing any round).
The entire solution elegantly handles all edge cases through mathematical operations without complex conditional logic.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through an example where you login at "09:07" and logout at "09:38".
Step 1: Convert times to minutes from midnight
- loginTime "09:07" → 9 × 60 + 7 = 547 minutes
- logoutTime "09:38" → 9 × 60 + 38 = 578 minutes
Step 2: Check for midnight wraparound
- Is 547 > 578? No, so no adjustment needed
- a = 547, b = 578
Step 3: Find round boundaries
-
Round up login time to next round start:
- a = (547 + 14) // 15 = 561 // 15 = 37
- This means the first complete round we can play is round #37 (which starts at 37 × 15 = 555 minutes, or 09:15)
-
Round down logout time to previous round start:
- b = 578 // 15 = 38
- This means the last complete round we can finish is round #38 (which ends at 38 × 15 + 15 = 585 minutes, or 09:45)
- Note: We logged out at 09:38, so we can't complete the round that starts at 09:30
Step 4: Calculate complete rounds
- Number of rounds = max(0, 38 - 37) = 1
Let's verify: The only complete round we played was from 09:15 to 09:30. We logged in at 09:07 (before 09:15 started) and logged out at 09:38 (after 09:30 ended), so we were present for the entire 15-minute duration of exactly one round.
Example with midnight wraparound: Login at "23:50", logout at "00:25"
- Convert: a = 23 × 60 + 50 = 1430 minutes, b = 0 × 60 + 25 = 25 minutes
- Check wraparound: 1430 > 25? Yes! So b = 25 + 1440 = 1465 minutes
- Round boundaries: a = (1430 + 14) // 15 = 96, b = 1465 // 15 = 97
- Complete rounds = max(0, 97 - 96) = 1
The one complete round is from 00:00 to 00:15 (we're logged in from 23:50 to 00:25, covering this entire round).
Solution Implementation
1class Solution:
2 def numberOfRounds(self, loginTime: str, logoutTime: str) -> int:
3 def convert_to_minutes(time_str: str) -> int:
4 """Convert time string (HH:MM) to total minutes since midnight."""
5 hours = int(time_str[:2])
6 minutes = int(time_str[3:])
7 return hours * 60 + minutes
8
9 # Convert both times to minutes since midnight
10 login_minutes = convert_to_minutes(loginTime)
11 logout_minutes = convert_to_minutes(logoutTime)
12
13 # Handle case where logout is next day (login after logout time)
14 if login_minutes > logout_minutes:
15 logout_minutes += 1440 # Add 24 hours (1440 minutes)
16
17 # Round up login time to next 15-minute interval
18 # Adding 14 ensures we round up to the next quarter hour
19 login_rounds = (login_minutes + 14) // 15
20
21 # Round down logout time to previous 15-minute interval
22 logout_rounds = logout_minutes // 15
23
24 # Calculate number of complete rounds, ensuring non-negative result
25 return max(0, logout_rounds - login_rounds)
26
1class Solution {
2 /**
3 * Calculates the number of full 15-minute rounds played between login and logout times.
4 * A round starts at :00, :15, :30, or :45 of each hour.
5 *
6 * @param loginTime The login time in "HH:MM" format
7 * @param logoutTime The logout time in "HH:MM" format
8 * @return The number of complete 15-minute rounds played
9 */
10 public int numberOfRounds(String loginTime, String logoutTime) {
11 // Convert time strings to total minutes since midnight
12 int loginMinutes = convertToMinutes(loginTime);
13 int logoutMinutes = convertToMinutes(logoutTime);
14
15 // Handle case where logout is on the next day (logout time < login time)
16 if (loginMinutes > logoutMinutes) {
17 logoutMinutes += 1440; // Add 24 hours (1440 minutes)
18 }
19
20 // Calculate complete rounds:
21 // - Round up login time to next 15-minute mark: (loginMinutes + 14) / 15
22 // - Round down logout time to previous 15-minute mark: logoutMinutes / 15
23 // - The difference gives us the number of complete rounds
24 return Math.max(0, logoutMinutes / 15 - (loginMinutes + 14) / 15);
25 }
26
27 /**
28 * Converts a time string to total minutes since midnight.
29 *
30 * @param timeString Time in "HH:MM" format
31 * @return Total minutes since midnight
32 */
33 private int convertToMinutes(String timeString) {
34 // Extract hours (first 2 characters)
35 int hours = Integer.parseInt(timeString.substring(0, 2));
36 // Extract minutes (characters at index 3 and 4)
37 int minutes = Integer.parseInt(timeString.substring(3, 5));
38
39 // Convert to total minutes
40 return hours * 60 + minutes;
41 }
42}
43
1class Solution {
2public:
3 int numberOfRounds(string loginTime, string logoutTime) {
4 // Lambda function to convert time string "HH:MM" to total minutes
5 auto convertToMinutes = [](string& timeStr) {
6 int hours, minutes;
7 sscanf(timeStr.c_str(), "%d:%d", &hours, &minutes);
8 return hours * 60 + minutes;
9 };
10
11 // Convert login and logout times to minutes since midnight
12 int loginMinutes = convertToMinutes(loginTime);
13 int logoutMinutes = convertToMinutes(logoutTime);
14
15 // If logout time is earlier than login time, it means logout happened the next day
16 // Add 24 hours (1440 minutes) to logout time
17 if (loginMinutes > logoutMinutes) {
18 logoutMinutes += 1440;
19 }
20
21 // Calculate the number of complete 15-minute rounds
22 // For login: round up to the next 15-minute mark using (loginMinutes + 14) / 15
23 // For logout: round down to the previous 15-minute mark using logoutMinutes / 15
24 // The difference gives us the number of complete rounds
25 return max(0, logoutMinutes / 15 - (loginMinutes + 14) / 15);
26 }
27};
28
1/**
2 * Calculates the number of complete 15-minute rounds between start and finish times
3 * @param startTime - Start time in "HH:MM" format
4 * @param finishTime - Finish time in "HH:MM" format
5 * @returns Number of complete 15-minute rounds
6 */
7function numberOfRounds(startTime: string, finishTime: string): number {
8 /**
9 * Converts time string to total minutes since midnight
10 * @param timeString - Time in "HH:MM" format
11 * @returns Total minutes since midnight
12 */
13 const convertToMinutes = (timeString: string): number => {
14 const [hours, minutes] = timeString.split(':').map(Number);
15 return hours * 60 + minutes;
16 };
17
18 // Convert both times to minutes
19 let startMinutes: number = convertToMinutes(startTime);
20 let finishMinutes: number = convertToMinutes(finishTime);
21
22 // If finish time is before start time, it means the activity spans midnight
23 // Add 24 hours (1440 minutes) to finish time to handle overnight scenarios
24 if (startMinutes > finishMinutes) {
25 finishMinutes += 1440;
26 }
27
28 // Calculate complete rounds:
29 // - Math.floor(finishMinutes / 15): last complete round that can finish before/at finish time
30 // - Math.ceil(startMinutes / 15): first complete round that can start after/at start time
31 // - The difference gives us the number of complete rounds
32 return Math.max(0, Math.floor(finishMinutes / 15) - Math.ceil(startMinutes / 15));
33}
34
Time and Space Complexity
The time complexity is O(1)
because:
- The function
f(s: str)
performs a constant number of operations: extracting substrings and converting them to integers, which takes constant time for fixed-length time strings - The main function performs a fixed sequence of operations regardless of input:
- Two calls to function
f
- One comparison (
a > b
) - One conditional addition
- Two division operations
- One
max
operation with two arguments
- Two calls to function
- All these operations execute in constant time
The space complexity is O(1)
because:
- The function uses only a fixed number of integer variables (
a
andb
) - No data structures that grow with input size are created
- The helper function
f
also uses constant space for its local computation - The total memory usage remains constant regardless of the input values
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Rounding Logic for Login Time
A common mistake is using standard rounding ((login_minutes + 7) // 15
) or ceiling division without proper adjustment. This can cause issues when the login time is exactly at a round boundary.
Pitfall Example:
# Incorrect approach login_rounds = (login_minutes + 15 - 1) // 15 # Wrong!
If someone logs in at exactly 09:00 (540 minutes), this would incorrectly round up to the next interval, missing the 09:00-09:15 round.
Solution:
The correct formula (login_minutes + 14) // 15
handles all cases:
- If login is at 09:00 (540 minutes):
(540 + 14) // 15 = 36
(correct) - If login is at 09:01 (541 minutes):
(541 + 14) // 15 = 37
(rounds up correctly)
2. Forgetting the Midnight Wraparound Check
Developers often forget to handle the case where a session spans across midnight, leading to negative results or incorrect calculations.
Pitfall Example:
# Missing midnight check login_minutes = convert_to_minutes(loginTime) logout_minutes = convert_to_minutes(logoutTime) # Directly calculating without checking if login > logout
Solution: Always check and adjust for midnight crossing:
if login_minutes > logout_minutes: logout_minutes += 1440 # Add 24 hours
3. Not Handling Edge Cases with max(0, ...)
Without the max(0, ...)
wrapper, the solution could return negative values when someone logs out before completing any round.
Pitfall Example: Login at 09:07, logout at 09:10:
- Login rounds:
(547 + 14) // 15 = 37
- Logout rounds:
550 // 15 = 36
- Result:
36 - 37 = -1
(incorrect!)
Solution:
Always use max(0, logout_rounds - login_rounds)
to ensure non-negative results.
4. String Parsing Errors
Assuming different time formats or using incorrect indices can cause parsing failures.
Pitfall Example:
# Assuming single-digit hours don't have leading zeros
hours = int(time_str[0]) if time_str[1] == ':' else int(time_str[:2]) # Wrong assumption!
Solution: The problem guarantees "HH:MM" format with leading zeros, so always use:
hours = int(time_str[:2])
minutes = int(time_str[3:])
You are given an array of intervals where intervals[i] = [start_i, end_i]
represent the start and end of the ith
interval. You need to merge all overlapping intervals and return an array of the non-overlapping intervals that cover all the intervals in the input.
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!