Strong Password Checker II
EasyPrompt
A password is said to be strong if it satisfies all the following criteria:
- It has at least
8characters. - It contains at least one lowercase letter.
- It contains at least one uppercase letter.
- It contains at least one digit.
- It contains at least one special character. The special characters are the characters in the following string:
"!@#$%^&*()-+". - It does not contain
2of the same character in adjacent positions (i.e.,"aab"violates this condition, but"aba"does not).
Given a string password, return true if it is a strong password. Otherwise, return false.
Example 1:
Input: password = "IloveLe3tcode!"
Output: true
Explanation: The password meets all the requirements. Therefore, we return true.Example 2:
Input: password = "Me+You--IsMyDream"
Output: false
Explanation: The password does not contain a digit and also contains 2 of the same character in adjacent positions. Therefore, we return false.Example 3:
Input: password = "1aB!"
Output: false
Explanation: The password does not meet the length requirement. Therefore, we return false.
Constraints:
1 <= password.length <= 100passwordconsists of letters, digits, and special characters:"!@#$%^&*()-+".
Approaches
2 approaches with complexity analysis and trade-offs.
This approach uses regular expressions (regex) to validate most of the password criteria. Regular expressions provide a powerful and declarative way to define patterns for string matching. However, for this specific problem, checking for adjacent identical characters is cumbersome with regex, so a separate loop is still needed for that condition.
Algorithm
- Check if
password.length()is less than 8. If so, returnfalse. - Iterate from the first to the second-to-last character of the password. In each iteration, check if
password.charAt(i)is equal topassword.charAt(i + 1). If they are equal, returnfalse. - Use the regex pattern
.*[a-z].*to check for the presence of a lowercase letter. If not found, returnfalse. - Use the regex pattern
.*[A-Z].*to check for the presence of an uppercase letter. If not found, returnfalse. - Use the regex pattern
.*\\d.*to check for the presence of a digit. If not found, returnfalse. - Use the regex pattern
.*[!@#$%^&*()+-].*to check for the presence of a special character. If not found, returnfalse. - If all checks pass, return
true.
Walkthrough
The overall logic is to check each of the six conditions.
- Length Check: First, we verify if the password's length is at least 8. If not, we immediately return
false. - Adjacent Character Check: We iterate through the password string with a simple loop to ensure no two adjacent characters are the same. This is easier to do with a loop than with a complex negative lookahead in regex. If we find a pair, we return
false. - Character Type Checks: For the remaining four conditions (presence of lowercase, uppercase, digit, and special character), we use separate regex patterns.
.*[a-z].*checks for at least one lowercase letter..*[A-Z].*checks for at least one uppercase letter..*\\d.*checks for at least one digit..*[!@#$%^&*()+-].*checks for at least one special character. We compile each pattern and match it against the password. The final result istrueonly if all these checks pass.
import java.util.regex.Pattern; class Solution { public boolean strongPasswordCheckerII(String password) { if (password.length() < 8) { return false; } // Check for adjacent identical characters for (int i = 0; i < password.length() - 1; i++) { if (password.charAt(i) == password.charAt(i + 1)) { return false; } } // Regex for character types boolean hasLower = Pattern.compile(".*[a-z].*").matcher(password).matches(); if (!hasLower) return false; boolean hasUpper = Pattern.compile(".*[A-Z].*").matcher(password).matches(); if (!hasUpper) return false; boolean hasDigit = Pattern.compile(".*\\d.*").matcher(password).matches(); if (!hasDigit) return false; // Note: Hyphen '-' needs to be escaped or placed at the end inside [] boolean hasSpecial = Pattern.compile(".*[!@#$%^&*()+-].*").matcher(password).matches(); if (!hasSpecial) return false; return true; }}Complexity
Time
O(N), where N is the length of the password. The loop for adjacent characters takes O(N) time. Each regex match also takes O(N) time in the worst case. Since we perform a constant number of passes, the total time complexity is linear.
Space
O(1). The space used by the regex engine is typically constant for these simple patterns and does not scale with the input size.
Trade-offs
Pros
Code can be concise and declarative for the character type checks.
Cons
Generally slower than a manual single-pass loop due to the overhead of compiling and executing regular expressions.
The check for adjacent characters doesn't fit neatly into the regex approach, requiring a separate loop.
Regex patterns can be less readable for developers not familiar with them.
Solutions
Solution
class Solution {public boolean strongPasswordCheckerII(String password) { if (password.length() < 8) { return false; } int mask = 0; for (int i = 0; i < password.length(); ++i) { char c = password.charAt(i); if (i > 0 && c == password.charAt(i - 1)) { return false; } if (Character.isLowerCase(c)) { mask |= 1; } else if (Character.isUpperCase(c)) { mask |= 2; } else if (Character.isDigit(c)) { mask |= 4; } else { mask |= 8; } } return mask == 15; }}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.