Student Attendance Record I: Single-Pass String Check
LeetCode 551, Student Attendance Record I, asks you to determine whether a student qualifies for an attendance award based on their record string. Each character is either 'A' (absent), 'L' (late), or 'P' (present). The eligibility rules are simple, but they require you to track two different conditions simultaneously as you scan the string. This makes it a great exercise in maintaining multiple pieces of state in a single pass.
The problem
A student's attendance record is a string of characters where each character is one of 'A', 'L', or 'P'. The student is eligible for an attendance award if both of these conditions are met:
- The student was absent (
'A') for strictly fewer than 2 days total. - The student was never late (
'L') for 3 or more consecutive days.
Given a string s, return True if the student is eligible, or False otherwise.
For example, "PPALLP" returns True because there is only 1 absence and only 2 consecutive lates. But "PPALLL" returns False because there are 3 consecutive lates.
The approach
You can solve this in a single pass through the string. Keep two counters:
absent_count: how many'A'characters you have seen so far.consec_late: how many consecutive'L'characters you have seen ending at the current position.
As you scan each character, update these counters. If the character is 'A', increment absent_count. If the character is 'L', increment consec_late. For anything else (including 'A'), reset consec_late to 0. At any point, if absent_count reaches 2 or consec_late reaches 3, you can immediately return False.
The consecutive late counter must reset whenever you see a non-'L' character. An 'A' in the middle of lates breaks the streak, so "LALL" has at most 1 consecutive late at any point after the 'A'.
The solution
def checkRecord(s):
absent_count = 0
consec_late = 0
for ch in s:
if ch == 'A':
absent_count += 1
consec_late = 0
if absent_count >= 2:
return False
elif ch == 'L':
consec_late += 1
if consec_late >= 3:
return False
else:
consec_late = 0
return True
Here is how each piece works:
- Absent check. When you see
'A', increment the absent counter and reset the consecutive late streak. If absences hit 2, returnFalseimmediately. - Late check. When you see
'L', increment the consecutive late counter. If it reaches 3, returnFalseimmediately. - Present (or any other character). Reset the consecutive late counter to 0. The absent counter stays the same.
- Default return. If you finish scanning without either condition triggering, the student is eligible.
Step-by-step walkthrough
Let's trace through a record that fails the consecutive late rule.
Walkthrough: record = "PPALLL" (not eligible)
Step 1: Initialize and read index 0
Character is 'P'. Not 'A', so absent count stays 0. Not 'L', so consecutive late resets to 0.
Step 2: Read index 1
Character is 'P'. Same as before. Absent count stays 0, consecutive late stays 0.
Step 3: Read index 2
Character is 'A'. Increment absent count to 1. Reset consecutive late to 0. Still under the limit of 2.
Step 4: Read index 3
Character is 'L'. Increment consecutive late to 1. Absent count unchanged.
Step 5: Read index 4
Character is 'L'. Increment consecutive late to 2. Still under the limit of 3.
Step 6: Read index 5
Character is 'L'. Consecutive late becomes 3. That is 3 or more consecutive lates!
FalseResult: Not eligible
The student has 3 consecutive lates, which violates the rule. Return False.
FalseThe walkthrough shows how the consecutive late counter climbs to 3 at index 5, triggering an immediate False return. The absent count never reached 2, but that does not matter because the consecutive late rule was violated first.
Complexity analysis
| Approach | Time | Space |
|---|---|---|
| Single pass | O(n) | O(1) |
You visit each character exactly once, so the time is O(n) where n is the length of the string. You only maintain two integer counters, so space is O(1).
The building blocks
Character counting and consecutive tracking
This problem combines two common string scanning patterns:
- Global counting. Counting how many times a specific character appears across the entire string. You use this for the absent check.
- Consecutive streak tracking. Maintaining a running count that resets whenever the streak breaks. You use this for the late check.
Both patterns are useful independently, but this problem forces you to run them in parallel within the same loop. That combination appears in many real-world validation tasks: checking log files for repeated errors, validating input sequences, or scanning sensor data for anomalies.
Whenever a problem asks about both a total count and a consecutive run, think about maintaining two separate counters in one pass. One increments globally, the other resets on breaks. This avoids multiple passes or extra data structures.
Edge cases
- All
'P'characters."PPPPPP"returnsTrue. Zero absences, zero lates. - Exactly one
'A'."PA"returnsTrue. One absence is still below the threshold. - Exactly two
'A's."PAPA"returnsFalse. Two absences violates the first rule. - Exactly two consecutive
'L's."PLL"returnsTrue. The limit is 3 or more, so 2 is fine. - Exactly three consecutive
'L's."PLLL"returnsFalse. Three consecutive lates triggers the rule. - Lates separated by other characters.
"LLPLL"returnsTrue. The consecutive streak resets at'P', so the maximum streak is 2. - Empty string.
""returnsTrue. No characters means no violations. - Single character.
"A"returnsTrue(1 absence, which is< 2)."L"returnsTrue."P"returnsTrue. - Worst case at boundaries.
"AALL"returnsFalsebecause there are 2 absences, even though the consecutive lates are only 2.
From understanding to recall
Student Attendance Record I is a clean example of maintaining multiple state variables in a single scan. The logic itself is simple. The value of practicing it comes from internalizing the pattern of parallel counters: one that accumulates globally and one that resets on breaks. Three weeks from now, when you face a string problem that asks you to check two different conditions simultaneously, you want this pattern to come to mind immediately rather than requiring you to think from scratch.
Spaced repetition helps you reach that point. By revisiting this problem at increasing intervals, you train yourself to recognize the "count + streak" pattern and write the solution without hesitation.
Related posts
- Longest Substring Without Repeating Characters - Another single-pass string problem that tracks state as you scan
- Find the Index of the First Occurrence in a String - String scanning with a different matching goal
- Detect Capital - Another easy string validation problem checking character patterns
CodeBricks uses spaced repetition to help you internalize patterns like this one. Instead of solving hundreds of problems once and forgetting them, you revisit the key patterns at scientifically optimized intervals until they become automatic.