Problem 2299

Abstract / Summary

Check if a password meets rules for length, character types, and no three identical consecutive characters.

Note

The full problem description, including helpful examples, can be found on LeetCode.

Python 2299.py

class Solution:
    def strongPasswordCheckerII(self, password: str) -> bool:
        # (1) It has at least 8 characters.
        if len(password) < 8:
            return False

        rule2 = False # (2) It contains at least one lowercase letter.
        rule3 = False # (3) It contains at least one uppercase letter.
        rule4 = False # (4) It contains at least one digit.
        rule5 = False # (5) It contains at least one special character.
                      #     The special characters are the characters in the following string:
                      #     "!@#$%^&*()-+"
                      # (6) It does not contain 2 of the same character in adjacent positions
                      #     (i.e., "aab" violates this condition, but "aba" does not).
        last  = ""
        for c in password:
            if   "a" <= c <= "z":
                rule2 = True
            elif "A" <= c <= "Z":
                rule3 = True
            elif "0" <= c <= "9":
                rule4 = True
            elif c in "!@#$%^&*()-+":
                rule5 = True

            if c == last:
                return False
            last = c

        return rule2 and rule3 and rule4 and rule5
30 lines | 1232 bytes | submitted January 5, 2024 | GitHub   45% comment ratio | tab size 4 | moderate complexity

Difficulty

This problem is ranked as
easy medium hard

and has an acceptance rate of about 56% (100k+ submissions).

Typical patterns to solve this problem:
  • String
I solved 663 easy, 1250 medium and 309 hard problems

AI Disclaimer

Every single line of code was written by me, 100% from scratch, between August 2023 and August 2024.
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.

See this dedicated page for more details.
LeetCode profile | GitHub repo

Code Walkthrough

Overview

The provided implementation defines a method that validates whether a given password satisfies a set of six security rules. The function proceeds in a linear fashion: it first checks the minimum length, then iterates through the characters once, updating flags that record the presence of required character classes while simultaneously detecting any adjacent duplicate characters. The final result is the logical conjunction of the four presence flags, which are only evaluated after the loop completes.

Length Verification

The very first operation is a guard clause that returns False immediately if the password length is less than eight characters. This early exit prevents any further processing for inputs that cannot possibly satisfy the policy, saving work for short strings.

if len(password) < 8:
    return False

Flag Initialization

Four Boolean variables are created to track the discovery of lowercase letters, uppercase letters, digits, and special characters. All are initialized to False. An additional variable, last, holds the previous character to enable adjacency checking.

rule2 = False   # lowercase present
rule3 = False   # uppercase present
rule4 = False   # digit present
rule5 = False   # special character present
last  = ""

Single-Pass Character Classification

The core of the algorithm is a for loop that examines each character exactly once. Inside the loop, a series of chained comparisons determines the character class:

  • The range "a" <= c <= "z" identifies lowercase letters.
  • The range "A" <= c <= "Z" identifies uppercase letters.
  • The range "0" <= c <= "9" identifies digits.
  • Membership in the literal string "!@#$%^&*()-+" identifies allowed special symbols.

When a character matches a class, the corresponding flag is set to True. Because the flags are only ever set to True, there is no need to reset them, and the loop does not perform any redundant work once a flag has been satisfied.

for c in password:
    if   "a" <= c <= "z":
        rule2 = True
    elif "A" <= c <= "Z":
        rule3 = True
    elif "0" <= c <= "9":
        rule4 = True
    elif c in "!@#$%^&*()-+":
        rule5 = True

Adjacent Duplicate Detection

Immediately after classifying the character, the algorithm compares it with the previously seen character stored in last. If the two are identical, the function returns False on the spot, halting further iteration. This early termination avoids unnecessary processing for passwords that already violate the adjacency rule.

    if c == last:
        return False
    last = c

Final Decision

After the loop finishes, the method returns the logical and of the four presence flags. Because the length and adjacency conditions have already been enforced, the final expression confirms that the password contains at least one character from each required class.

return rule2 and rule3 and rule4 and rule5

Edge Cases Handled

The code gracefully handles several boundary conditions:

  • An empty string fails the length check instantly.
  • A string exactly eight characters long proceeds to the loop, ensuring that the minimum length requirement is inclusive.
  • Passwords composed solely of characters from a single required class (e.g., only digits) will leave the other flags False, causing the final conjunction to evaluate to False.
  • Strings that contain a repeated character at any position, including the first two characters, trigger the adjacency check and return False without scanning the remainder.
  • Passwords that include characters outside the defined special set are simply ignored for the special-character flag, allowing the function to focus only on the permitted symbols.

Performance Optimizations

The implementation exhibits several efficiency choices:

  • Early length guard eliminates work for obviously invalid inputs.
  • Single traversal ensures that each character is examined only once, achieving the minimal number of passes required for the rule set.
  • Immediate adjacency failure returns as soon as a duplicate is found, preventing the rest of the password from being processed.
  • Flag setting without resetting means each flag is written at most once per password, avoiding unnecessary assignments after a flag becomes True.
  • Use of range comparisons ("a" <= c <= "z") leverages the underlying character ordering, which is faster than invoking methods like str.islower().
  • Membership test against a literal string for special characters is a constant-time operation because the string is short and Python optimizes such containment checks.

Collectively, these decisions keep the runtime proportional to the length of the password while minimizing overhead per character.

written by openai gpt

ELI5 - Simplified Explanation

Think of this code like a guard standing at the front door to check if a password is strong enough to keep a secret safe. The code looks at the word you picked like a detective investigating clues.

First, the guard uses a tape measure to make sure the password is at least eight letters long because short passwords are too easy for someone to guess. If it is too short, the guard shakes their head and says it does not work.

Next, the code walks through every letter in the word one by one. It keeps a mental checklist in its pocket to see if the word has a small letter, a big letter, a number, and a special sign like an exclamation point or a plus sign. If it finds one of these, it puts a checkmark on its list.

While it looks at the letters, the guard also watches to see if two of the same letter are standing right next to each other, like a pair of twins holding hands. If it sees twins, it stops immediately because that would make the password less secure.

Finally, after looking at the whole password, the guard checks its pocket list. If all four checkmarks are there and no twins were spotted standing together, the password passes the test and is ready to keep everything safe inside.

written by google gemini

Code Quality

Several LLMs ranked my code quality on a scale from 1 (very poor) to 10 (outstanding):
n = 27 | median = 8 | μ = 7.70 | σ = 1.05

Complexity Analysis

Time: linear
As a rule of thumb, the maximum input size for one second execution time is
  • factorial: up to 10 elements
  • exponential: up to 20 elements
  • polynomial: a few thousand elements
  • loglinear: up to 100,000 elements
  • linear: a few million elements
  • logarithmic: a billion elements
  • constant: practically unlimited
generated automatically

Other Solutions

I wrote a basic crawler to find other solutions to that problem.
Obviously, I did that after I solved the problem myself.

In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.

And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.

(click on a column header to sort the table)
author
author solutions
www AlgoMonster Java Python C++ TS
WalkCCC Java Python C++
leetcode.ca Java Python C++ C Go Rust TS
Progiez Java Python C++
github charles-wangkai Java
fartem Ruby
fsq C++
JoshCrozier JS
lkwq007 Python
varunu28 Java
AlgoMonster C++, Python, Java, TypeScript
WalkCCC C++, Python, Java
leetcode.ca C, C++, Go, Java, Python, Rust, TypeScript
Progiez C++, Java, Python
charles-wangkai Java
fartem Ruby
fsq C++
JoshCrozier JavaScript
lkwq007 Python
varunu28 Java
23 links | 10 authors | 9 languages

Videos

5 videos   did my crawler come up with invalid videos ? drop me a line.

Similar Problems

1 similar problem

Solved On The Same Day

5 solutions   January 5, 2024

Extra

There are a few extra pages giving you some insights into my setup:
  • Tech Stack - my development environment and tools
  • AI - how AI helped me create this website (NOT solving the problems)
  • Progress - progression over time
  • Quality - code quality