Count Days Spent Together
EasyPrompt
Alice and Bob are traveling to Rome for separate business meetings.
You are given 4 strings arriveAlice, leaveAlice, arriveBob, and leaveBob. Alice will be in the city from the dates arriveAlice to leaveAlice (inclusive), while Bob will be in the city from the dates arriveBob to leaveBob (inclusive). Each will be a 5-character string in the format "MM-DD", corresponding to the month and day of the date.
Return the total number of days that Alice and Bob are in Rome together.
You can assume that all dates occur in the same calendar year, which is not a leap year. Note that the number of days per month can be represented as: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31].
Example 1:
Input: arriveAlice = "08-15", leaveAlice = "08-18", arriveBob = "08-16", leaveBob = "08-19"
Output: 3
Explanation: Alice will be in Rome from August 15 to August 18. Bob will be in Rome from August 16 to August 19. They are both in Rome together on August 16th, 17th, and 18th, so the answer is 3.Example 2:
Input: arriveAlice = "10-01", leaveAlice = "10-31", arriveBob = "11-01", leaveBob = "12-31"
Output: 0
Explanation: There is no day when Alice and Bob are in Rome together, so we return 0.
Constraints:
- All dates are provided in the format
"MM-DD". - Alice and Bob's arrival dates are earlier than or equal to their leaving dates.
- The given dates are valid dates of a non-leap year.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach simulates the calendar year and marks the days each person is in Rome. We can use two boolean arrays, one for Alice and one for Bob, of size 366 (to represent days 1 to 365). We first convert the given 'MM-DD' date strings into the corresponding day of the year. Then, we iterate through the date ranges for both Alice and Bob, marking the corresponding days as true in their respective arrays. Finally, we iterate through the arrays one more time to count the number of days where both Alice and Bob are present (i.e., both arrays have true at the same index).
Algorithm
- Define an array
daysInMonthto store the number of days in each month for a non-leap year:[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]. - Create a helper function,
getDayOfYear(String date), that takes a date string 'MM-DD' and converts it to an integer representing the day of the year (from 1 to 365). This function will parse the month and day, and use thedaysInMontharray to calculate the total number of days. - In the main function, convert all four input date strings (
arriveAlice,leaveAlice,arriveBob,leaveBob) into their day-of-the-year integer representations using the helper function. - Initialize two boolean arrays,
alicePresenceandbobPresence, of size 366, with all values asfalse. - Iterate from Alice's arrival day to her leave day, setting
alicePresence[day] = truefor each day. - Do the same for Bob, setting
bobPresence[day] = truefor each day he is in Rome. - Initialize a counter
commonDaysto 0. - Iterate from day 1 to 365. If
alicePresence[day]andbobPresence[day]are bothtrue, incrementcommonDays. - Return
commonDays.
Walkthrough
class Solution { public int countDaysSpentTogether(String arriveAlice, String leaveAlice, String arriveBob, String leaveBob) { int[] daysInMonth = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Create a prefix sum array for quick lookup for (int i = 1; i < daysInMonth.length; i++) { daysInMonth[i] += daysInMonth[i-1]; } int arriveAliceDay = getDayOfYear(arriveAlice, daysInMonth); int leaveAliceDay = getDayOfYear(leaveAlice, daysInMonth); int arriveBobDay = getDayOfYear(arriveBob, daysInMonth); int leaveBobDay = getDayOfYear(leaveBob, daysInMonth); boolean[] alicePresence = new boolean[366]; boolean[] bobPresence = new boolean[366]; for (int i = arriveAliceDay; i <= leaveAliceDay; i++) { alicePresence[i] = true; } for (int i = arriveBobDay; i <= leaveBobDay; i++) { bobPresence[i] = true; } int commonDays = 0; for (int i = 1; i <= 365; i++) { if (alicePresence[i] && bobPresence[i]) { commonDays++; } } return commonDays; } private int getDayOfYear(String date, int[] prefixSum) { int month = Integer.parseInt(date.substring(0, 2)); int day = Integer.parseInt(date.substring(3, 5)); return prefixSum[month - 1] + day; }}Complexity
Time
O(N), where N is the number of days in a year (365). The conversion of dates is constant time. The main work involves three loops: one to mark Alice's days, one for Bob's, and one to find common days. In the worst case, these loops run up to N times. Since N is a fixed constant (365), the complexity is technically O(1), but it's less efficient than a direct mathematical calculation.
Space
O(N), where N is the number of days in a year. We use two boolean arrays of size 366 to store the presence of Alice and Bob for each day of the year.
Trade-offs
Pros
The logic is straightforward and easy to follow, as it directly models the problem statement.
It's a robust approach that can be easily adapted if the rules for presence become more complex (e.g., non-contiguous days).
Cons
Uses more memory than necessary by creating two large arrays.
The time complexity is proportional to the number of days in the year, which is inefficient compared to a direct calculation.
A more efficient approach is to treat the problem as finding the length of the intersection of two intervals on a number line. First, we convert all dates into a single, comparable unit: the day of the year (an integer from 1 to 365). Alice's stay is an interval [startA, endA] and Bob's is [startB, endB]. The period they spend together is the intersection of these two intervals. The start of this intersection is the latest of the two arrival dates, and the end is the earliest of the two departure dates. If the calculated start of the overlap is after the end, it means there is no overlap.
Algorithm
- Define a helper function or use a precomputed array to convert 'MM-DD' date strings into the day of the year (an integer from 1 to 365). A common way is to use a prefix sum array of the number of days in each month.
- Convert the four input dates into four integers:
aliceArrivalDay,aliceLeaveDay,bobArrivalDay,bobLeaveDay. - Determine the start of the overlapping period by finding the maximum of the two arrival days:
startOfOverlap = Math.max(aliceArrivalDay, bobArrivalDay). - Determine the end of the overlapping period by finding the minimum of the two leave days:
endOfOverlap = Math.min(aliceLeaveDay, bobLeaveDay). - Calculate the duration of the overlap. The number of days is
endOfOverlap - startOfOverlap + 1. - If
startOfOverlapis greater thanendOfOverlap, the intervals do not overlap, and the number of common days is 0. This can be handled by takingMath.max(0, duration). - Return the calculated number of days.
Walkthrough
class Solution { public int countDaysSpentTogether(String arriveAlice, String leaveAlice, String arriveBob, String leaveBob) { int[] days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // Create a prefix sum array for quick lookup for (int i = 1; i < days.length; i++) { days[i] += days[i-1]; } int arriveAliceDay = getDayOfYear(arriveAlice, days); int leaveAliceDay = getDayOfYear(leaveAlice, days); int arriveBobDay = getDayOfYear(arriveBob, days); int leaveBobDay = getDayOfYear(leaveBob, days); int latestArrival = Math.max(arriveAliceDay, arriveBobDay); int earliestLeave = Math.min(leaveAliceDay, leaveBobDay); int overlap = earliestLeave - latestArrival + 1; return Math.max(0, overlap); } private int getDayOfYear(String date, int[] prefixSum) { int month = Integer.parseInt(date.substring(0, 2)); int day = Integer.parseInt(date.substring(3, 5)); return prefixSum[month - 1] + day; }}Complexity
Time
O(1). The process involves a fixed number of operations: four date conversions (each constant time), two comparisons (`Math.max`, `Math.min`), and one subtraction. The complexity does not depend on the length of the date intervals.
Space
O(1). We only need a few variables to store the calculated day numbers. The array to store the number of days in months has a fixed size (13), which is constant space.
Trade-offs
Pros
Extremely efficient in both time and space.
The solution is concise and based on a simple mathematical principle.
Cons
Requires recognizing the problem as an interval intersection problem, which might be slightly less intuitive than direct simulation.
Solutions
Solution
class Solution {private int[] days = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};public int countDaysTogether(String arriveAlice, String leaveAlice, String arriveBob, String leaveBob) { String a = arriveAlice.compareTo(arriveBob) < 0 ? arriveBob : arriveAlice; String b = leaveAlice.compareTo(leaveBob) < 0 ? leaveAlice : leaveBob; int x = f(a), y = f(b); return Math.max(y - x + 1, 0); }private int f(String s) { int i = Integer.parseInt(s.substring(0, 2)) - 1; int res = 0; for (int j = 0; j < i; ++j) { res += days[j]; } res += Integer.parseInt(s.substring(3)); return res; }}class Solution: def countDaysTogether(self, arriveAlice: str, leaveAlice: str, arriveBob: str, leaveBob: str) -> int: a = max(arriveAlice, arriveBob) b = min(leaveAlice, leaveBob) days = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) x = sum(days[: int(a[: 2]) - 1]) + int(a[3:]) y = sum(days[: int(b[: 2]) - 1]) + int(b[3:]) return max(y - x + 1, 0)class Solution {public: vector<int> days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int countDaysTogether(string arriveAlice, string leaveAlice, string arriveBob, string leaveBob) { string a = arriveAlice < arriveBob ? arriveBob : arriveAlice; string b = leaveAlice < leaveBob ? leaveAlice : leaveBob; int x = f(a), y = f(b); return max(0, y - x + 1); } int f(string s) { int m, d; sscanf(s.c_str(), "%d-%d", &m, &d); int res = 0; for (int i = 0; i < m - 1; ++i) { res += days[i]; } res += d; return res; }};Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.