Problem#
Given a password entered by the user, check if it is strong. If it is not strong, suggest a strong password by modifying the input minimally (add missing character types, increase length, etc.).
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: "!@#$%^&*()-+"
.
Examples#
Example 1#
1
2
3
Input: password = "Abc123"
Output: "Abc123!x"
Explanation: The password is too short and missing a special character. Adding "!x" makes it strong.
Example 2#
1
2
3
Input: password = "aabbccdd"
Output: "aB1!bccd"
Explanation: The password is missing an uppercase letter, a digit, and a special character, and has adjacent duplicates. The suggestion fixes all issues.
Example 3#
1
2
3
Input: password = "IloveK5kc!"
Output: "IloveK5kc!"
Explanation: The password is already strong.
Method 1 – Greedy Validation and Minimal Fixes#
Intuition#
The key idea is to check for all required password properties (length, lowercase, uppercase, digit, special character, no adjacent duplicates). If any property is missing, we add or modify characters as needed, always making the minimal change. For suggestions, we fix missing types, break up adjacent duplicates, and pad the password to the required length.
Approach#
Check if the password meets all criteria:
At least 8 characters.
At least one lowercase, one uppercase, one digit, one special character.
No two identical adjacent characters.
If strong, return the password as is.
Otherwise:
Insert missing character types at the earliest opportunity.
Break up adjacent duplicates by inserting a non-duplicate character.
If the password is too short, append random valid characters to reach length 8.
Ensure all fixes are minimal and the result is strong.
Code#
Cpp
Go
Java
Kotlin
Python
Rust
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public :
std:: string suggestStrongPassword(std:: string password) {
std:: string specials = "!@#$%^&*()-+" ;
bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (char c : password) {
if (islower(c)) hasLower = true;
else if (isupper(c)) hasUpper = true;
else if (isdigit(c)) hasDigit = true;
else if (specials.find(c) != std:: string:: npos) hasSpecial = true;
}
std:: string ans = password;
if (! hasLower) ans += 'a' ;
if (! hasUpper) ans += 'A' ;
if (! hasDigit) ans += '1' ;
if (! hasSpecial) ans += '!' ;
// Break adjacent duplicates
for (int i = 1 ; i < (int )ans.size(); ++ i) {
if (ans[i] == ans[i- 1 ]) {
ans.insert(ans.begin() + i, (ans[i] == 'a' ? 'B' : 'a' ));
++ i;
}
}
while ((int )ans.size() < 8 ) ans += 'x' ;
if ((int )ans.size() > 100 ) ans = ans.substr(0 , 100 );
return ans;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
func suggestStrongPassword (password string ) string {
specials := "!@#$%^&*()-+"
hasLower , hasUpper , hasDigit , hasSpecial := false , false , false , false
for _ , c := range password {
switch {
case c >= 'a' && c <= 'z' :
hasLower = true
case c >= 'A' && c <= 'Z' :
hasUpper = true
case c >= '0' && c <= '9' :
hasDigit = true
case strings .ContainsRune (specials , c ):
hasSpecial = true
}
}
ans := password
if !hasLower {
ans += "a"
}
if !hasUpper {
ans += "A"
}
if !hasDigit {
ans += "1"
}
if !hasSpecial {
ans += "!"
}
res := []rune(ans )
for i := 1 ; i < len(res ); i ++ {
if res [i ] == res [i - 1 ] {
ch := 'a'
if res [i ] == 'a' {
ch = 'B'
}
res = append(res [:i ], append([]rune {ch }, res [i :]... )... )
i ++
}
}
for len(res ) < 8 {
res = append(res , 'x' )
}
if len(res ) > 100 {
res = res [:100 ]
}
return string(res )
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public String suggestStrongPassword (String password) {
String specials = "!@#$%^&*()-+" ;
boolean hasLower = false , hasUpper = false , hasDigit = false , hasSpecial = false ;
for (char c : password.toCharArray ()) {
if (Character.isLowerCase (c)) hasLower = true ;
else if (Character.isUpperCase (c)) hasUpper = true ;
else if (Character.isDigit (c)) hasDigit = true ;
else if (specials.indexOf (c) != - 1) hasSpecial = true ;
}
StringBuilder ans = new StringBuilder(password);
if (! hasLower) ans.append ('a' );
if (! hasUpper) ans.append ('A' );
if (! hasDigit) ans.append ('1' );
if (! hasSpecial) ans.append ('!' );
for (int i = 1; i < ans.length (); i++ ) {
if (ans.charAt (i) == ans.charAt (i- 1)) {
ans.insert (i, ans.charAt (i) == 'a' ? 'B' : 'a' );
i++ ;
}
}
while (ans.length () < 8) ans.append ('x' );
if (ans.length () > 100) ans.setLength (100);
return ans.toString ();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
fun suggestStrongPassword (password: String): String {
val specials = "!@#$%^&*()-+"
var hasLower = false
var hasUpper = false
var hasDigit = false
var hasSpecial = false
for (c in password) {
when {
c.isLowerCase() -> hasLower = true
c.isUpperCase() -> hasUpper = true
c.isDigit() -> hasDigit = true
specials.contains(c) -> hasSpecial = true
}
}
val ans = StringBuilder(password)
if (!hasLower) ans.append('a' )
if (!hasUpper) ans.append('A' )
if (!hasDigit) ans.append('1' )
if (!hasSpecial) ans.append('!' )
var i = 1
while (i < ans.length) {
if (ans[i] == ans[i-1 ]) {
ans.insert(i, if (ans[i] == 'a' ) 'B' else 'a' )
i++
}
i++
}
while (ans.length < 8 ) ans.append('x' )
if (ans.length > 100 ) ans.setLength(100 )
return ans.toString()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution :
def suggestStrongPassword (self, password: str) -> str:
specials = "!@#$%^&*()-+"
has_lower = any(c. islower() for c in password)
has_upper = any(c. isupper() for c in password)
has_digit = any(c. isdigit() for c in password)
has_special = any(c in specials for c in password)
ans = password
if not has_lower:
ans += 'a'
if not has_upper:
ans += 'A'
if not has_digit:
ans += '1'
if not has_special:
ans += '!'
res = [ans[0 ]] if ans else []
for c in ans[1 :]:
if res and c == res[- 1 ]:
res. append('B' if c == 'a' else 'a' )
res. append(c)
while len(res) < 8 :
res. append('x' )
if len(res) > 100 :
res = res[:100 ]
return '' . join(res)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
impl Solution {
pub fn suggest_strong_password (password: String) -> String {
let specials = "!@#$%^&*()-+" ;
let mut has_lower = false ;
let mut has_upper = false ;
let mut has_digit = false ;
let mut has_special = false ;
for c in password.chars() {
if c.is_ascii_lowercase() { has_lower = true ; }
else if c.is_ascii_uppercase() { has_upper = true ; }
else if c.is_ascii_digit() { has_digit = true ; }
else if specials.contains(c) { has_special = true ; }
}
let mut ans = password;
if ! has_lower { ans.push('a' ); }
if ! has_upper { ans.push('A' ); }
if ! has_digit { ans.push('1' ); }
if ! has_special { ans.push('!' ); }
let mut res: Vec< char > = ans.chars().collect();
let mut i = 1 ;
while i < res.len() {
if res[i] == res[i- 1 ] {
res.insert(i, if res[i] == 'a' { 'B' } else { 'a' });
i += 1 ;
}
i += 1 ;
}
while res.len() < 8 {
res.push('x' );
}
if res.len() > 100 {
res.truncate(100 );
}
res.into_iter().collect()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
suggestStrongPassword (password : string ): string {
const specials = "!@#$%^&*()-+" ;
let hasLower = false , hasUpper = false , hasDigit = false , hasSpecial = false ;
for (const c of password ) {
if (c >= 'a' && c <= 'z' ) hasLower = true ;
else if (c >= 'A' && c <= 'Z' ) hasUpper = true ;
else if (c >= '0' && c <= '9' ) hasDigit = true ;
else if (specials .includes (c )) hasSpecial = true ;
}
let ans = password ;
if (! hasLower ) ans += 'a' ;
if (! hasUpper ) ans += 'A' ;
if (! hasDigit ) ans += '1' ;
if (! hasSpecial ) ans += '!' ;
let res = ans .length ? [ans [0 ]] : [];
for (let i = 1 ; i < ans .length ; i ++ ) {
if (ans [i ] === ans [i - 1 ]) res .push (ans [i ] === 'a' ? 'B' : 'a' );
res .push (ans [i ]);
}
while (res .length < 8 ) res .push ('x' );
if (res .length > 100 ) res = res .slice (0 , 100 );
return res .join ('' );
}
}
Complexity#
⏰ Time complexity: O(n)
— We scan the password and build the suggestion in a single pass, where n is the length of the password.
🧺 Space complexity: O(n)
— We may build a new string of up to O(n) length for the suggestion.