2409. Count Days Spent Together
Problem Description
Alice and Bob are planning separate trips to Rome. You need to calculate how many days they will both be in the city at the same time.
You are given four date strings:
arriveAlice
: The date Alice arrives in RomeleaveAlice
: The date Alice leaves RomearriveBob
: The date Bob arrives in RomeleaveBob
: The date Bob leaves Rome
Each date is formatted as "MM-DD"
(a 5-character string where MM is the month and DD is the day). Both the arrival and departure dates are inclusive, meaning if someone arrives on "03-15"
and leaves on "03-17"
, they are in Rome for 3 days (15th, 16th, and 17th).
Your task is to find the total number of days when both Alice and Bob are in Rome together. If their stays don't overlap at all, return 0.
The problem guarantees:
- All dates are in the same calendar year
- The year is not a leap year (February has 28 days)
- The days per month follow:
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
For example, if Alice is in Rome from "08-15"
to "08-18"
and Bob is in Rome from "08-16"
to "08-19"
, they overlap for 3 days (16th, 17th, and 18th).
The solution approach converts each date to the day number of the year (1-365), finds the overlapping period by taking the later arrival date and earlier departure date, then calculates the difference. If the result is negative (no overlap), it returns 0.
Intuition
To find the overlap between two time periods, we need to think about when an overlap actually occurs. Two periods overlap when one starts before the other ends, and vice versa. The overlapping period, if it exists, starts at the later of the two arrival dates and ends at the earlier of the two departure dates.
Working with dates in "MM-DD"
format is cumbersome for calculations. A key insight is to convert dates to a single number - the day of the year. For instance, "01-01"
becomes day 1, "01-31"
becomes day 31, and "02-01"
becomes day 32. This transformation allows us to use simple arithmetic to find the overlap.
Once we have the dates as day numbers:
- The overlap starts on day
max(arriveAlice_day, arriveBob_day)
- The overlap ends on day
min(leaveAlice_day, leaveBob_day)
- The number of overlapping days is
end - start + 1
(we add 1 because both endpoints are inclusive)
If the calculated end day is before the start day, it means there's no overlap, so we return 0.
The conversion formula for a date "MM-DD"
to day of year is: sum up all the days in the months before month MM, then add DD. For example, "03-05"
(March 5th) would be 31 (January) + 28 (February) + 5 = 64
, making it the 64th day of the year.
This approach elegantly handles all edge cases - whether one person's entire stay is within the other's, partial overlaps, or no overlap at all - through the simple max(end - start + 1, 0)
calculation.
Learn more about Math patterns.
Solution Approach
The implementation follows a straightforward approach of converting dates to day-of-year numbers and finding the overlap:
Step 1: Find the overlap period boundaries
a = max(arriveAlice, arriveBob)
: Gets the later arrival date (start of potential overlap)b = min(leaveAlice, leaveBob)
: Gets the earlier departure date (end of potential overlap)
Since the date strings are in "MM-DD"
format, string comparison works correctly here. For example, "08-15"
> "08-10"
and "09-01"
> "08-31"
.
Step 2: Define days per month
days = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
: A tuple storing the number of days in each month (0-indexed)
Step 3: Convert dates to day-of-year numbers
-
For the start date
a
:int(a[:2])
extracts the month (first 2 characters)sum(days[:int(a[:2]) - 1])
sums all days in months before this monthint(a[3:])
extracts the day (characters after the hyphen)x = sum(days[:int(a[:2]) - 1]) + int(a[3:])
gives the day number of the year
-
Similarly for end date
b
:y = sum(days[:int(b[:2]) - 1]) + int(b[3:])
For example, if a = "03-05"
:
- Month = 3, Day = 5
- Days before March =
sum(days[:2])
=31 + 28 = 59
- Day of year =
59 + 5 = 64
Step 4: Calculate overlapping days
max(y - x + 1, 0)
:- If
y >= x
, there's an overlap ofy - x + 1
days (inclusive counting) - If
y < x
, there's no overlap, so return 0
- If
The max(..., 0)
ensures we never return a negative number when there's no overlap between Alice and Bob's stays.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach.
Example:
- Alice arrives:
"08-15"
and leaves:"08-18"
- Bob arrives:
"08-16"
and leaves:"08-19"
Step 1: Find overlap boundaries
- Start of overlap:
a = max("08-15", "08-16") = "08-16"
(Bob arrives later) - End of overlap:
b = min("08-18", "08-19") = "08-18"
(Alice leaves earlier)
Step 2: Set up days per month
days = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
Step 3: Convert to day-of-year numbers
For start date "08-16"
:
- Month = 8, Day = 16
- Days in months before August:
sum(days[:7]) = 31 + 28 + 31 + 30 + 31 + 30 + 31 = 212
- Day of year:
x = 212 + 16 = 228
For end date "08-18"
:
- Month = 8, Day = 18
- Days in months before August:
sum(days[:7]) = 212
(same as above) - Day of year:
y = 212 + 18 = 230
Step 4: Calculate overlap
- Overlapping days:
max(230 - 228 + 1, 0) = max(3, 0) = 3
The result is 3 days, which matches our expectation: they're both in Rome on August 16th, 17th, and 18th.
Edge Case Example - No Overlap:
If Alice leaves "08-15"
and Bob arrives "08-16"
:
- Start:
a = "08-16"
→ day 228 - End:
b = "08-15"
→ day 227 - Overlap:
max(227 - 228 + 1, 0) = max(0, 0) = 0
The algorithm correctly returns 0 when there's no overlap.
Solution Implementation
1class Solution:
2 def countDaysTogether(
3 self, arriveAlice: str, leaveAlice: str, arriveBob: str, leaveBob: str
4 ) -> int:
5 """
6 Calculate the number of days Alice and Bob are together.
7
8 Args:
9 arriveAlice: Alice's arrival date in "MM-DD" format
10 leaveAlice: Alice's departure date in "MM-DD" format
11 arriveBob: Bob's arrival date in "MM-DD" format
12 leaveBob: Bob's departure date in "MM-DD" format
13
14 Returns:
15 Number of days both are present together
16 """
17 # Find the overlapping period
18 # Latest arrival date (start of overlap)
19 overlap_start = max(arriveAlice, arriveBob)
20 # Earliest departure date (end of overlap)
21 overlap_end = min(leaveAlice, leaveBob)
22
23 # Days in each month (non-leap year)
24 days_in_month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
25
26 # Convert start date to day of year
27 # Extract month and day from "MM-DD" format
28 start_month = int(overlap_start[:2])
29 start_day = int(overlap_start[3:])
30 # Calculate total days from January 1st to start date
31 start_day_of_year = sum(days_in_month[:start_month - 1]) + start_day
32
33 # Convert end date to day of year
34 end_month = int(overlap_end[:2])
35 end_day = int(overlap_end[3:])
36 # Calculate total days from January 1st to end date
37 end_day_of_year = sum(days_in_month[:end_month - 1]) + end_day
38
39 # Calculate overlapping days (inclusive of both start and end)
40 # If end is before start, there's no overlap, return 0
41 return max(end_day_of_year - start_day_of_year + 1, 0)
42
1class Solution {
2 // Days in each month (non-leap year)
3 private int[] daysInMonth = new int[] {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
4
5 /**
6 * Counts the number of days Alice and Bob are in town together.
7 *
8 * @param arriveAlice Alice's arrival date in "MM-DD" format
9 * @param leaveAlice Alice's departure date in "MM-DD" format
10 * @param arriveBob Bob's arrival date in "MM-DD" format
11 * @param leaveBob Bob's departure date in "MM-DD" format
12 * @return The number of days they are both in town
13 */
14 public int countDaysTogether(
15 String arriveAlice, String leaveAlice, String arriveBob, String leaveBob) {
16
17 // Find the later arrival date (start of overlap period)
18 String overlapStart = arriveAlice.compareTo(arriveBob) < 0 ? arriveBob : arriveAlice;
19
20 // Find the earlier departure date (end of overlap period)
21 String overlapEnd = leaveAlice.compareTo(leaveBob) < 0 ? leaveAlice : leaveBob;
22
23 // Convert dates to day of year
24 int startDay = convertToDayOfYear(overlapStart);
25 int endDay = convertToDayOfYear(overlapEnd);
26
27 // Calculate overlap days (inclusive), return 0 if no overlap
28 return Math.max(endDay - startDay + 1, 0);
29 }
30
31 /**
32 * Converts a date string to the day number of the year.
33 *
34 * @param dateString Date in "MM-DD" format
35 * @return The day number of the year (1-365)
36 */
37 private int convertToDayOfYear(String dateString) {
38 // Extract month (convert from 1-based to 0-based index)
39 int monthIndex = Integer.parseInt(dateString.substring(0, 2)) - 1;
40
41 // Sum up days from all previous months
42 int totalDays = 0;
43 for (int month = 0; month < monthIndex; month++) {
44 totalDays += daysInMonth[month];
45 }
46
47 // Add the day of the current month
48 totalDays += Integer.parseInt(dateString.substring(3));
49
50 return totalDays;
51 }
52}
53
1class Solution {
2public:
3 // Days in each month (non-leap year)
4 vector<int> daysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5
6 /**
7 * Calculate the number of days when both Alice and Bob are in the city together
8 * @param arriveAlice - Alice's arrival date in "MM-DD" format
9 * @param leaveAlice - Alice's departure date in "MM-DD" format
10 * @param arriveBob - Bob's arrival date in "MM-DD" format
11 * @param leaveBob - Bob's departure date in "MM-DD" format
12 * @return Number of days both are present in the city
13 */
14 int countDaysTogether(string arriveAlice, string leaveAlice, string arriveBob, string leaveBob) {
15 // Find the overlapping period
16 // Start of overlap: latest arrival date
17 string overlapStart = arriveAlice < arriveBob ? arriveBob : arriveAlice;
18
19 // End of overlap: earliest departure date
20 string overlapEnd = leaveAlice < leaveBob ? leaveAlice : leaveBob;
21
22 // Convert dates to day of year
23 int startDay = convertDateToDayOfYear(overlapStart);
24 int endDay = convertDateToDayOfYear(overlapEnd);
25
26 // Calculate overlap days (inclusive), return 0 if no overlap
27 return max(0, endDay - startDay + 1);
28 }
29
30private:
31 /**
32 * Convert a date string to the day number of the year
33 * @param dateString - Date in "MM-DD" format
34 * @return Day number of the year (1-365)
35 */
36 int convertDateToDayOfYear(string dateString) {
37 int month, day;
38
39 // Parse month and day from the date string
40 sscanf(dateString.c_str(), "%d-%d", &month, &day);
41
42 // Calculate total days from January 1st
43 int totalDays = 0;
44
45 // Add days from all previous months
46 for (int i = 0; i < month - 1; ++i) {
47 totalDays += daysInMonth[i];
48 }
49
50 // Add days in the current month
51 totalDays += day;
52
53 return totalDays;
54 }
55};
56
1// Days in each month (non-leap year)
2const daysInMonth: number[] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
3
4/**
5 * Convert a date string to the day number of the year
6 * @param dateString - Date in "MM-DD" format
7 * @return Day number of the year (1-365)
8 */
9function convertDateToDayOfYear(dateString: string): number {
10 // Parse month and day from the date string
11 const [month, day] = dateString.split('-').map(num => parseInt(num));
12
13 // Calculate total days from January 1st
14 let totalDays = 0;
15
16 // Add days from all previous months
17 for (let i = 0; i < month - 1; i++) {
18 totalDays += daysInMonth[i];
19 }
20
21 // Add days in the current month
22 totalDays += day;
23
24 return totalDays;
25}
26
27/**
28 * Calculate the number of days when both Alice and Bob are in the city together
29 * @param arriveAlice - Alice's arrival date in "MM-DD" format
30 * @param leaveAlice - Alice's departure date in "MM-DD" format
31 * @param arriveBob - Bob's arrival date in "MM-DD" format
32 * @param leaveBob - Bob's departure date in "MM-DD" format
33 * @return Number of days both are present in the city
34 */
35function countDaysTogether(arriveAlice: string, leaveAlice: string, arriveBob: string, leaveBob: string): number {
36 // Find the overlapping period
37 // Start of overlap: latest arrival date
38 const overlapStart = arriveAlice < arriveBob ? arriveBob : arriveAlice;
39
40 // End of overlap: earliest departure date
41 const overlapEnd = leaveAlice < leaveBob ? leaveAlice : leaveBob;
42
43 // Convert dates to day of year
44 const startDay = convertDateToDayOfYear(overlapStart);
45 const endDay = convertDateToDayOfYear(overlapEnd);
46
47 // Calculate overlap days (inclusive), return 0 if no overlap
48 return Math.max(0, endDay - startDay + 1);
49}
50
Time and Space Complexity
The time complexity is O(C)
, where C
is a constant. This is because:
- Parsing the month and day from the date strings takes
O(1)
time - The
sum()
function is called twice on slices of thedays
tuple, but since there are at most 12 months, each sum operation takes at mostO(12) = O(1)
time - The
max()
andmin()
operations on strings areO(1)
since date strings have fixed length - All other operations (integer conversions, arithmetic) are
O(1)
The space complexity is O(C)
, where C
is a constant. This is because:
- The
days
tuple stores exactly 12 integers, requiringO(12) = O(1)
space - Variables
a
,b
,x
, andy
each store a single value, requiringO(1)
space - No data structures that grow with input size are used
Since all operations and storage requirements are bounded by constants independent of input size, both complexities are O(C)
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrect Overlap Calculation - Off-by-One Error
The most common mistake is forgetting to add 1 when calculating the number of overlapping days. Since both arrival and departure dates are inclusive, the formula should be end - start + 1
, not just end - start
.
Incorrect Implementation:
# Wrong - missing the +1
return max(end_day_of_year - start_day_of_year, 0)
Why it's wrong: If Alice and Bob are both in Rome on the same single day (e.g., both on day 100), the calculation would give 100 - 100 = 0
days, when it should be 1 day.
Correct Implementation:
# Correct - includes both endpoints
return max(end_day_of_year - start_day_of_year + 1, 0)
2. Incorrect Month Indexing When Calculating Day of Year
Another frequent error is mishandling the month index when summing days. Since months are 1-indexed (January = 1) but the days_in_month
tuple is 0-indexed, you need to subtract 1 from the month number.
Incorrect Implementation:
# Wrong - doesn't account for 0-based indexing
start_day_of_year = sum(days_in_month[:start_month]) + start_day
Why it's wrong: For March 5th (month = 3), this would sum days for January, February, AND March (indices 0, 1, 2), adding an extra 31 days.
Correct Implementation:
# Correct - properly handles the indexing
start_day_of_year = sum(days_in_month[:start_month - 1]) + start_day
3. String Parsing Errors
Be careful with string slicing indices. The date format is "MM-DD"
with the hyphen at index 2.
Incorrect Implementation:
# Wrong indices for day extraction
start_day = int(overlap_start[2:]) # Would include the hyphen
Correct Implementation:
# Correct - skips the hyphen at index 2
start_day = int(overlap_start[3:]) # Gets characters from index 3 onward
Complete Corrected Solution:
class Solution:
def countDaysTogether(
self, arriveAlice: str, leaveAlice: str, arriveBob: str, leaveBob: str
) -> int:
# Find overlap boundaries
overlap_start = max(arriveAlice, arriveBob)
overlap_end = min(leaveAlice, leaveBob)
# Days per month (non-leap year)
days_in_month = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
# Convert to day of year (remember: month-1 for 0-based indexing)
start_day_of_year = sum(days_in_month[:int(overlap_start[:2]) - 1]) + int(overlap_start[3:])
end_day_of_year = sum(days_in_month[:int(overlap_end[:2]) - 1]) + int(overlap_end[3:])
# Calculate overlap (remember: +1 for inclusive counting)
return max(end_day_of_year - start_day_of_year + 1, 0)
In a binary min heap, the minimum element can be found in:
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!