Talentd
FleetCode
Make and follow sheets.Sign in

Strong Password Checker II solution and explanation

EasyString5 min read55.5% acceptanceUpdated 9 Apr 2026
LeetCode 2299 – How to Check Strong Passwords in Java (Easy Explanation)Recurso · 15:44 · 577 viewsWatch on YouTube
6 more videos on this problem
  1. LeetCode 2299 – How to Check Strong Passwords in Java (Easy Explanation)Recurso · 15:44 · 577 views
  2. 2299. Strong Password Checker II (Leetcode Easy)Programming Live with Larry · 3:40 · 524 views
  3. LeetCode 2299 | Strong Password Checker II | HashSet | String | JavaSleepy Cracker · 4:36 · 463 views
  4. Leetcode BiWeekly contest 80 Strong Password Checker IIPrakhar Agrawal · 4:17 · 398 views
  5. LeetCode 2299. Strong Password Checker IIYuki Kitayama · 12:45 · 128 views
  6. Strong Password Checker II || Leetcode Biweekly Contest 80 || Easysangramsinh sawant · 3:10 · 127 views
  7. Leetcode 2299 Strong Password Checker II - Explained In HindiAlgorithmicIQ · 10:32 · 53 views

The problem

A password is said to be strong if it satisfies all the following criteria:

  • It has at least 8 characters.
  • 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 2 of 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 <= 100
  • password consists of letters, digits, and special characters: "!@#$%^&*()-+".

Approach overview

Problem Overview: You are given a password string and must determine if it qualifies as a strong password. A valid password must be at least 8 characters long, contain lowercase, uppercase, digit, and special characters, and must not have identical adjacent characters. The task is essentially a rule validation problem on a string.

Approach 1: Iterative Character Check (O(n) time, O(1) space)

Scan the password once while tracking whether each required category appears. During iteration, check if the current character is lowercase, uppercase, digit, or one of the allowed special characters. Maintain boolean flags for each requirement and immediately reject if two adjacent characters are equal. Because you only iterate through the string once and store a few flags, the solution runs in O(n) time with constant O(1) space.

This approach is straightforward and gives full control over each rule. It works well in interviews because you explicitly show how each condition is validated using simple character checks. The logic mostly relies on basic string traversal and conditional checks.

Approach 2: Regular Expression (O(n) time, O(1) space)

Another option is to validate the password using regular expressions. A regex pattern can enforce the presence of lowercase letters, uppercase letters, digits, and special characters using lookaheads. After the regex match, perform an additional scan to ensure no adjacent characters are identical.

The regex engine still processes the string linearly, so the complexity remains O(n) time with constant O(1) extra space. This method produces shorter code and is convenient when multiple character rules must be validated simultaneously. However, debugging complex regex patterns can be harder during interviews.

Recommended for interviews: The iterative character check approach is usually preferred. It clearly demonstrates how you validate constraints, detect adjacent duplicates, and manage state while scanning a string. Regex solutions are concise but may hide the underlying logic, while the iterative solution shows stronger problem-solving clarity.

Approach 1: Approach 1: Iterative Character Check

This approach involves iterating through each character of the password while maintaining flags that check for different conditions like uppercase, lowercase, digit, special character, and adjacent duplicates. Start by checking if the length of the password is at least 8. Update flags as you iterate through the password and check if two consecutive characters are the same. If all flags are true and no two consecutive characters are the same, then the password is strong.

def isStrongPassword(password: str) -> bool:
    if len(password) < 8:
        return False

    has_lower = has_upper = has_digit = has_special = False
    special_chars = "!@#$%^&*()-+"

    for i in range(len(password)):
        if password[i].islower():
            has_lower = True
        elif password[i].isupper():
            has_upper = True
        elif password[i].isdigit():
            has_digit = True
        elif password[i] in special_chars:
            has_special = True

        if i > 0 and password[i] == password[i - 1]:
            return False

    return has_lower and has_upper and has_digit and has_special
public class Solution {
    public boolean isStrongPassword(String password) {
        if (password.length() < 8) return false;

        boolean hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
        String specialChars = "!@#$%^&*()-+";

        for (int i = 0; i < password.length(); i++) {
            char c = password.charAt(i);
            if (Character.isLowerCase(c)) hasLower = true;
            else if (Character.isUpperCase(c)) hasUpper = true;
            else if (Character.isDigit(c)) hasDigit = true;
            else if (specialChars.indexOf(c) != -1) hasSpecial = true;

            if (i > 0 && password.charAt(i) == password.charAt(i - 1)) return false;
        }

        return hasLower && hasUpper && hasDigit && hasSpecial;
    }
}
#include <iostream>
#include <string>

bool isStrongPassword(const std::string& password) {
    if (password.length() < 8) return false;

    bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
    std::string specialChars = "!@#$%^&*()-+";

    for (size_t i = 0; i < password.size(); ++i) {
        char c = password[i];
        if (islower(c)) hasLower = true;
        else if (isupper(c)) hasUpper = true;
        else if (isdigit(c)) hasDigit = true;
        else if (specialChars.find(c) != std::string::npos) hasSpecial = true;

        if (i > 0 && password[i] == password[i - 1]) return false;
    }

    return hasLower && hasUpper && hasDigit && hasSpecial;
}
function isStrongPassword(password) {
    if (password.length < 8) return false;

    let hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
    const specialChars = "!@#$%^&*()-+";

    for (let i = 0; i < password.length; i++) {
        if (/[a-z]/.test(password[i])) hasLower = true;
        else if (/[A-Z]/.test(password[i])) hasUpper = true;
        else if (/[0-9]/.test(password[i])) hasDigit = true;
        else if (specialChars.includes(password[i])) hasSpecial = true;

        if (i > 0 && password[i] === password[i - 1]) return false;
    }

    return hasLower && hasUpper && hasDigit && hasSpecial;
}
#include <stdbool.h>
#include <ctype.h>
#include <string.h>

bool isStrongPassword(char * password){
    int n = strlen(password);
    if (n < 8) return false;

    bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
    char *specialChars = "!@#$%^&*()-+";

    for (int i = 0; i < n; i++) {
        if (islower(password[i])) hasLower = true;
        else if (isupper(password[i])) hasUpper = true;
        else if (isdigit(password[i])) hasDigit = true;
        else if (strchr(specialChars, password[i])) hasSpecial = true;

        if (i > 0 && password[i] == password[i - 1]) return false;
    }

    return hasLower && hasUpper && hasDigit && hasSpecial;
}
public class Solution {
    public bool IsStrongPassword(string password) {
        if (password.Length < 8) return false;

        bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
        string specialChars = "!@#$%^&*()-+";

        for (int i = 0; i < password.Length; i++) {
            char c = password[i];
            if (char.IsLower(c)) hasLower = true;
            else if (char.IsUpper(c)) hasUpper = true;
            else if (char.IsDigit(c)) hasDigit = true;
            else if (specialChars.Contains(c)) hasSpecial = true;

            if (i > 0 && password[i] == password[i - 1]) return false;
        }

        return hasLower && hasUpper && hasDigit && hasSpecial;
    }
}

Python's readability makes iterating through each condition clear with boolean storage and character checks using string methods.

Complexity

Time Complexity: O(n), Space Complexity: O(1).

Try this approach in the editor

Approach 2: Approach 2: Regular Expression

This method simplifies many checks by leveraging a regular expression to validate parts of the password rules. The regex checks can determine the presence of character types and length while additional logic ensures no adjacent duplicates are present. This approach makes the code cleaner but requires a good understanding of regex.

import re

def isStrongPassword(password: str) -> bool:
    if len(password) < 8:
        return False
    if not re.match(r'.*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()\-\+]).*', password):
        return False
    return all(password[i] != password[i - 1] for i in range(1, len(password)))
import java.util.regex.*;

public class Solution {
    public boolean isStrongPassword(String password) {
        if (password.length() < 8) return false;

        Pattern pattern = Pattern.compile(".*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()\-\+]).*");
        Matcher matcher = pattern.matcher(password);
        if (!matcher.matches()) return false;

        for (int i = 1; i < password.length(); i++) {
            if (password.charAt(i) == password.charAt(i - 1)) return false;
        }

        return true;
    }
}
#include <regex>
#include <string>

bool isStrongPassword(const std::string& password) {
    if (password.length() < 8) return false;
    std::regex re(".*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()\-\+]).*");
    if (!std::regex_match(password, re)) return false;
    for (size_t i = 1; i < password.length(); ++i) {
        if (password[i] == password[i - 1]) return false;
    }
    return true;
}
function isStrongPassword(password) {
    if (password.length < 8) return false;

    const regex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()\-\+]).+$/;
    if (!regex.test(password)) return false;

    for (let i = 1; i < password.length; i++) {
        if (password[i] === password[i - 1]) return false;
    }

    return true;
}
#include <stdbool.h>
#include <regex.h>
#include <string.h>

bool isStrongPassword(char * password){
    int n = strlen(password);
    if (n < 8) return false;

    regex_t regex;
    int reti;
    const char *pattern = ".*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()\-\+]).*";
    reti = regcomp(&regex, pattern, REG_EXTENDED);
    if (reti) return false;

    reti = regexec(&regex, password, 0, NULL, 0);
    regfree(&regex);
    if (reti) return false;

    for (int i = 1; i < n; i++) {
        if (password[i] == password[i - 1]) return false;
    }
    return true;
}
using System;
using System.Text.RegularExpressions;

public class Solution {
    public bool IsStrongPassword(string password) {
        if (password.Length < 8) return false;
        if (!Regex.IsMatch(password, ".*(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*()\-\+]).*")) return false;

        for (int i = 1; i < password.Length; i++) {
            if (password[i] == password[i - 1]) return false;
        }

        return true;
    }
}

Python's 're' module is suited for this purpose, allowing easy access to match operations tailored by your regular expression.

Complexity

Time Complexity: O(n), Space Complexity: O(1).

Try this approach in the editor

Approach 3: Simulation + Bit Manipulation

According to the problem description, we can simulate the process of checking whether the password meets the requirements.

First, we check if the length of the password is less than 8. If it is, we return false.

Next, we use a mask mask to record whether the password contains lowercase letters, uppercase letters, digits, and special characters. We traverse the password, and for each character, we first check if it is the same as the previous character. If it is, we return false. Then, we update the mask mask based on the character type. Finally, we check if the mask mask is 15. If it is, we return true; otherwise, we return false.

The time complexity is O(n), and the space complexity is O(1). Here, n is the length of the password.

function strongPasswordCheckerII(password: string): boolean {
    if (password.length < 8) {
        return false;
    }
    let mask = 0;
    for (let i = 0; i < password.length; ++i) {
        const c = password[i];
        if (i && c == password[i - 1]) {
            return false;
        }
        if (c >= 'a' && c <= 'z') {
            mask |= 1;
        } else if (c >= 'A' && c <= 'Z') {
            mask |= 2;
        } else if (c >= '0' && c <= '9') {
            mask |= 4;
        } else {
            mask |= 8;
        }
    }
    return mask == 15;
}
func strongPasswordCheckerII(password string) bool {
	if len(password) < 8 {
		return false
	}
	mask := 0
	for i, c := range password {
		if i > 0 && byte(c) == password[i-1] {
			return false
		}
		if unicode.IsLower(c) {
			mask |= 1
		} else if unicode.IsUpper(c) {
			mask |= 2
		} else if unicode.IsDigit(c) {
			mask |= 4
		} else {
			mask |= 8
		}
	}
	return mask == 15
}
impl Solution {
    pub fn strong_password_checker_ii(password: String) -> bool {
        let s = password.as_bytes();
        let n = password.len();
        if n < 8 {
            return false;
        }
        let mut mask = 0;
        let mut prev = b' ';
        for &c in s.iter() {
            if c == prev {
                return false;
            }
            mask |= if c.is_ascii_uppercase() {
                0b1000
            } else if c.is_ascii_lowercase() {
                0b100
            } else if c.is_ascii_digit() {
                0b10
            } else {
                0b1
            };
            prev = c;
        }
        mask == 0b1111
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Iterative Character Check

Time Complexity: O(n), Space Complexity: O(1).

Approach 2: Regular Expression

Time Complexity: O(n), Space Complexity: O(1).

Simulation + Bit Manipulation–

Complexity analysis

ApproachTimeSpaceWhen to Use
Iterative Character CheckO(n)O(1)Best general solution. Clear rule validation and preferred in coding interviews.
Regular ExpressionO(n)O(1)Useful when combining multiple character checks compactly using regex patterns.

Frequently asked questions

Is Strong Password Checker II easy or hard?

Strong Password Checker II is classified as an Easy problem. The main challenge is carefully implementing all validation rules—length requirement, character categories, allowed special characters, and preventing consecutive duplicates.

Strong Password Checker II Python/Java solution

Both Python and Java solutions typically implement a single loop over the password string. During iteration they track character categories and check adjacent duplicates. The implementation runs in O(n) time and uses constant extra space.

How to solve Strong Password Checker II in O(n)?

Iterate through the password string once and maintain flags for lowercase, uppercase, digit, and special characters. At each step also check whether the current character equals the previous one. After the scan, confirm that the length is at least 8 and all flags are true.

What is the best approach for Strong Password Checker II?

The best approach is a single-pass iterative character check. Iterate through the string once while tracking whether lowercase, uppercase, digit, and special characters appear, and ensure no adjacent characters are equal. This solution runs in O(n) time with O(1) space and is the most readable for interviews.

Is Strong Password Checker II asked at Google/Amazon/Meta?

Strong Password Checker II is a typical string validation problem similar to interview questions asked by companies like Amazon and Google. It tests attention to detail, rule validation, and efficient single-pass string processing.

What data structure is used in Strong Password Checker II?

The problem mainly uses simple string traversal. No complex data structures are required—only a few boolean flags and character comparisons while iterating through the string.

What is the time complexity of Strong Password Checker II?

The optimal solution runs in O(n) time where n is the length of the password. You scan the string once to validate all rules. Space complexity is O(1) because only a few boolean flags are stored.

Comments

Now write it yourselfClose this page and solve Strong Password Checker II in the editor, without looking.
Practise Strong Password Checker II