You are given an integer n
representing the length of an attendance record. An attendance record consists of the characters 'A' (Absent), 'L' (Late), and 'P' (Present).
A student is eligible for an attendance award if they meet both of the following conditions:
Your task is to write a function that calculates the number of possible attendance records of length n
that make a student eligible for an attendance award. Since the answer can be very large, return it modulo 10^9 + 7
.
Example 1:
n = 2
Output: 8
Explanation: The eligible records are "PP", "AP", "PA", "LP", "PL", "AL", "LA", "LL". "AA" is not eligible because it has 2 absences.
Example 2:
n = 1
Output: 3
Explanation: The eligible records are "A", "L", "P".
Constraints:
1 <= n <= 10^5
How would you approach solving this problem efficiently? What are the time and space complexities of your solution?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to find the number of valid attendance records of a given length. A brute force approach involves generating every single possible attendance record and then checking if each record is valid.
Here's how the algorithm would work step-by-step:
def student_attendance_record_two_brute_force(number_of_days):
all_possible_records = []
def generate_records(current_record, days_remaining):
if days_remaining == 0:
all_possible_records.append(current_record)
return
generate_records(current_record + 'P', days_remaining - 1)
generate_records(current_record + 'A', days_remaining - 1)
generate_records(current_record + 'L', days_remaining - 1)
generate_records('', number_of_days)
valid_record_count = 0
for record in all_possible_records:
absent_count = 0
late_streak = 0
is_valid = True
for day in record:
if day == 'A':
absent_count += 1
if day == 'L':
late_streak += 1
else:
late_streak = 0
# Check for invalid condition: more than one absent
if absent_count > 1:
is_valid = False
break
# Check for invalid condition: more than two consecutive lates
if late_streak > 2:
is_valid = False
break
if is_valid:
valid_record_count += 1
return valid_record_count
# Main function for testing the brute force approach.
def main_function(number_of_days):
# Call the brute force solution.
result = student_attendance_record_two_brute_force(number_of_days)
return result
This problem involves counting attendance records with specific constraints on the number of absent and late days. The efficient solution breaks down the problem into smaller, overlapping subproblems, solving each subproblem only once and storing the results to avoid redundant calculations.
Here's how the algorithm would work step-by-step:
def student_attendance_record_ii(record_length):
modulo = 10**9 + 7
# Initialize the dp array to store counts.
dp = [[[0] * 3 for _ in range(2)] for _ in range(record_length + 1)]
# Base case: Empty record
dp[0][0][0] = 1
for i in range(1, record_length + 1):
# Case 1: Present. Inherit counts from previous day.
for absent_count in range(2):
for late_count in range(3):
dp[i][absent_count][0] = (dp[i][absent_count][0] + dp[i-1][absent_count][late_count]) % modulo
# Case 2: Absent. Can only have one absent.
for late_count in range(3):
if 0 < 2:
dp[i][1][0] = (dp[i][1][0] + dp[i-1][0][late_count]) % modulo
# Case 3: Late. Can have at most two consecutive lates.
for absent_count in range(2):
for late_count in range(1, 3):
dp[i][absent_count][late_count] = (dp[i][absent_count][late_count] + dp[i-1][absent_count][late_count-1]) % modulo
total_attendance_records = 0
for absent_count in range(2):
for late_count in range(3):
total_attendance_records = (total_attendance_records + dp[record_length][absent_count][late_count]) % modulo
return total_attendance_records
Case | How to Handle |
---|---|
n = 0 | Return 1 as there is one way to have a record with length 0. |
n = 1 | Return 3 as there are three possibilities: A, L, P. |
n = 2 | Return 8, covering all possibilities: PP, PA, AP, AA, PL, LP, LA, AL. |
Maximum input size (n is large, e.g., 100000) | Use dynamic programming with memoization to avoid redundant calculations and ensure the solution scales efficiently; also, make sure to use modulo operation at each step to prevent integer overflow. |
Integer overflow when calculating combinations | Use modulo operator % (10^9 + 7) after each calculation to keep the result within the integer range. |
Input where only 'A' is allowed | The answer will be zero if n > 1 since more than one absent is not allowed. |
Input where no 'A' is allowed | Calculations change but still follow same dynamic programming or recursive methodology, summing possibilities of only L and P. |
When n is very large, the number of combinations becomes extremely large causing performance problems if not using dynamic programming. | Use dynamic programming for efficient computation, avoiding redundant calculations, for time complexity O(n). |