Skip to content

LeetCode 551: Student Attendance Record I

A clear explanation of Student Attendance Record I using simple string checks and a one-pass counter solution.

Problem Restatement

We are given a string s representing one student’s attendance record.

Each character has one meaning:

CharacterMeaning
"A"Absent
"L"Late
"P"Present

The student gets an attendance award only if both rules are satisfied:

  1. The student has strictly fewer than 2 absences in total.
  2. The student is never late for 3 or more consecutive days.

Return true if the student can receive the award. Otherwise, return false.

The official constraints are 1 <= s.length <= 1000, and every character is one of "A", "L", or "P".

Input and Output

ItemMeaning
InputA string s
OutputA boolean
Return true whens has at most one "A" and does not contain "LLL"
Return false whens has two or more "A" characters, or has three consecutive "L" characters

Example function shape:

def checkRecord(s: str) -> bool:
    ...

Examples

Example 1:

s = "PPALLP"

There is one absence:

"A" count = 1

There are two consecutive late days, but not three:

"LL" exists
"LLL" does not exist

So the answer is:

True

Example 2:

s = "PPALLL"

There is one absence, which is allowed.

But the string contains:

"LLL"

That means the student was late for three consecutive days.

So the answer is:

False

First Thought: Direct String Checks

The two award rules map directly to two string checks.

The absence rule says:

s.count("A") < 2

The late rule says:

"LLL" not in s

The student is eligible only when both are true:

s.count("A") < 2 and "LLL" not in s

This is already enough for this problem.

Algorithm

Use Python’s built-in string operations.

  1. Count how many times "A" appears.
  2. Check whether the substring "LLL" appears.
  3. Return true only if the absence count is less than 2 and "LLL" is not present.

Correctness

The award rule has exactly two conditions.

The expression:

s.count("A") < 2

is true exactly when the student has zero or one absence. This is exactly the first rule.

The expression:

"LLL" not in s

is true exactly when there is no block of at least three consecutive late days. Any longer block, such as "LLLL", also contains "LLL" inside it. So this check also rejects four, five, or more consecutive late days.

The algorithm returns the logical and of these two checks. Therefore, it returns true exactly when both award rules are satisfied, and returns false otherwise.

Complexity

Let n be the length of s.

MetricValueWhy
TimeO(n)Counting "A" scans the string, and checking "LLL" also scans the string
SpaceO(1)Only a few counters and fixed-size checks are needed

Implementation

class Solution:
    def checkRecord(self, s: str) -> bool:
        return s.count("A") < 2 and "LLL" not in s

Code Explanation

The first part checks the total absence count:

s.count("A") < 2

This allows 0 or 1 absence.

The second part checks the consecutive late rule:

"LLL" not in s

This rejects any record containing three consecutive late days.

The and operator means the student must satisfy both rules.

One-Pass Version

We can also solve the problem manually in one pass.

This version is useful when we want to avoid relying on substring search and make the state explicit.

class Solution:
    def checkRecord(self, s: str) -> bool:
        absent_count = 0
        late_streak = 0

        for ch in s:
            if ch == "A":
                absent_count += 1
                late_streak = 0

                if absent_count >= 2:
                    return False

            elif ch == "L":
                late_streak += 1

                if late_streak >= 3:
                    return False

            else:
                late_streak = 0

        return True

Here, absent_count tracks the total number of absences.

The variable late_streak tracks the current consecutive run of "L" characters.

Whenever we see "A" or "P", the late streak resets to 0, because the consecutive late run has ended.

Testing

def run_tests():
    s = Solution()

    assert s.checkRecord("PPALLP") is True
    assert s.checkRecord("PPALLL") is False
    assert s.checkRecord("A") is True
    assert s.checkRecord("AA") is False
    assert s.checkRecord("LL") is True
    assert s.checkRecord("LLL") is False
    assert s.checkRecord("PPLPLPL") is True
    assert s.checkRecord("LALL") is True
    assert s.checkRecord("ALLL") is False

    print("all tests passed")

run_tests()
TestWhy
"PPALLP"Valid record from the sample
"PPALLL"Invalid because of three consecutive late days
"A"One absence is allowed
"AA"Two absences are not allowed
"LL"Two consecutive late days are allowed
"LLL"Three consecutive late days are not allowed
"PPLPLPL"Many late days, but not consecutive
"LALL"Absence resets the late streak
"ALLL"Fails because of "LLL"