2299-强密码检验器 II

Raphael Liu Lv10

如果一个密码满足以下所有条件,我们称它是一个 密码:

  • 它有至少 8 个字符。
  • 至少包含 一个小写英文 字母。
  • 至少包含 一个大写英文 字母。
  • 至少包含 一个数字
  • 至少包含 一个特殊字符 。特殊字符为:"!@#%^&*()-+" 中的一个。
  • 包含 2 个连续相同的字符(比方说 "aab" 不符合该条件,但是 "aba" 符合该条件)。

给你一个字符串 password ,如果它是一个 密码,返回 true,否则返回 false

示例 1:

**输入:** password = "IloveLe3tcode!"
**输出:** true
**解释:** 密码满足所有的要求,所以我们返回 true 。

示例 2:

**输入:** password = "Me+You--IsMyDream"
**输出:** false
**解释:** 密码不包含数字,且包含 2 个连续相同的字符。所以我们返回 false 。

示例 3:

**输入:** password = "1aB!"
**输出:** false
**解释:** 密码不符合长度要求。所以我们返回 false 。

提示:

  • 1 <= password.length <= 100
  • password 包含字母,数字和 "!@#%^&*()-+" 这些特殊字符。

方法一:模拟

思路与算法

我们按照题目的要求模拟即可。

对于「它有至少 8 个字符」的要求,我们可以判断给定的字符串 password 的长度是否至少为 8。

对于「至少包含一个小写英文字母、一个大写英文字母、一个数字、一个特殊字符」的要求,我们各自使用一个布尔变量 hasLower}, \textit{hasUpper}, \textit{hasDigit}, \textit{hasSpecial 来进行记录。我们可以对字符串 password 进行一次遍历,如果遇到某一类型的字符,就将对应的布尔变量置为 True。

对于英文字母和数字,我们可以使用语言自带的 API 进行判断,也可以根据它们的 ASCII 码范围进行判断;对于特殊字符,我们可以提前将所有的特殊字符放入一个哈希表中,并判断遍历到的字符是否在哈希表中即可。

对于「不包含 2 个连续相同的字符」的要求,当我们遍历到字符串 password 的第 i 个字符时,如果它和第 i+1 个字符相同,那么我们直接返回 False。

代码

[sol1-C++]
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 {
public:
bool strongPasswordCheckerII(string password) {
if (password.size() < 8) {
return false;
}

unordered_set<char> specials = {'!', '@', '#', '', '%', '^', '&', '*', '(', ')', '-', '+'};
int n = password.size();
bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (int i = 0; i < n; ++i) {
if (i != n - 1 && password[i] == password[i + 1]) {
return false;
}

char ch = password[i];
if (islower(ch)) {
hasLower = true;
}
else if (isupper(ch)) {
hasUpper = true;
}
else if (isdigit(ch)) {
hasDigit = true;
}
else if (specials.count(ch)) {
hasSpecial = true;
}
}

return hasLower && hasUpper && hasDigit && hasSpecial;
}
};
[sol1-Java]
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
class Solution {
public boolean strongPasswordCheckerII(String password) {
if (password.length() < 8) {
return false;
}

Set<Character> specials = new HashSet<Character>() { {
add('!');
add('@');
add('#');
add('');
add('%');
add('^');
add('&');
add('*');
add('(');
add(')');
add('-');
add('+');
} };
int n = password.length();
boolean hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (int i = 0; i < n; ++i) {
if (i != n - 1 && password.charAt(i) == password.charAt(i + 1)) {
return false;
}

char ch = password.charAt(i);
if (Character.isLowerCase(ch)) {
hasLower = true;
} else if (Character.isUpperCase(ch)) {
hasUpper = true;
} else if (Character.isDigit(ch)) {
hasDigit = true;
} else if (specials.contains(ch)) {
hasSpecial = true;
}
}

return hasLower && hasUpper && hasDigit && hasSpecial;
}
}
[sol1-C#]
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
public class Solution {
public bool StrongPasswordCheckerII(string password) {
if (password.Length < 8) {
return false;
}

ISet<char> specials = new HashSet<char>() {'!', '@', '#', '', '%', '^', '&', '*', '(', ')', '-', '+'};
int n = password.Length;
bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (int i = 0; i < n; ++i) {
if (i != n - 1 && password[i] == password[i + 1]) {
return false;
}

char ch = password[i];
if (char.IsLower(ch)) {
hasLower = true;
} else if (char.IsUpper(ch)) {
hasUpper = true;
} else if (char.IsDigit(ch)) {
hasDigit = true;
} else if (specials.Contains(ch)) {
hasSpecial = true;
}
}

return hasLower && hasUpper && hasDigit && hasSpecial;
}
}
[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution:
def strongPasswordCheckerII(self, password: str) -> bool:
if len(password) < 8:
return False

specials = set("!@#%^&*()-+")
hasLower = hasUpper = hasDigit = hasSpecial = False

for i, ch in enumerate(password):
if i != len(password) - 1 and password[i] == password[i + 1]:
return False

if ch.islower():
hasLower = True
elif ch.isupper():
hasUpper = True
elif ch.isdigit():
hasDigit = True
elif ch in specials:
hasSpecial = True

return hasLower and hasUpper and hasDigit and hasSpecial
[sol1-C]
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
bool strongPasswordCheckerII(char * password) {
int n = strlen(password);
if (n < 8) {
return false;
}
char *specialChars = "!@#%^&*()-+";
bool specials[128];
memset(specials, 0, sizeof(specials));
for (int i = 0; i < specialChars[i] != '\0'; i++) {
specials[specialChars[i]] = true;
}
bool hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (int i = 0; i < n; ++i) {
if (i != n - 1 && password[i] == password[i + 1]) {
return false;
}

char ch = password[i];
if (islower(ch)) {
hasLower = true;
}
else if (isupper(ch)) {
hasUpper = true;
}
else if (isdigit(ch)) {
hasDigit = true;
}
else if (specials[ch]) {
hasSpecial = true;
}
}
return hasLower && hasUpper && hasDigit && hasSpecial;
}
[sol1-JavaScript]
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
var strongPasswordCheckerII = function(password) {
if (password.length < 8) {
return false;
}

const specials = new Set();
specials.add('!');
specials.add('@');
specials.add('#');
specials.add('');
specials.add('%');
specials.add('^');
specials.add('&');
specials.add('*');
specials.add('(');
specials.add(')');
specials.add('-');
specials.add('+');
const n = password.length;
let hasLower = false, hasUpper = false, hasDigit = false, hasSpecial = false;
for (let i = 0; i < n; ++i) {
if (i !== n - 1 && password[i] === password[i + 1]) {
return false;
}

const ch = password[i];
if (isLowerCase(ch)) {
hasLower = true;
} else if (isUpperCase(ch)) {
hasUpper = true;
} else if (isDigit(ch)) {
hasDigit = true;
} else if (specials.has(ch)) {
hasSpecial = true;
}
}
return hasLower && hasUpper && hasDigit && hasSpecial;
};

const isDigit = (ch) => {
return parseFloat(ch).toString() === "NaN" ? false : true;
}

const isLowerCase = str => 'a' <= str && str <= 'z';

const isUpperCase = str => 'A' <= str && str <= 'Z';
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func strongPasswordCheckerII(password string) bool {
n := len(password)
if n < 8 {
return false
}

var hasLower, hasUpper, hasDigit, hasSpecial bool
for i, ch := range password {
if i != n-1 && password[i] == password[i+1] {
return false
}
if unicode.IsLower(ch) {
hasLower = true
} else if unicode.IsUpper(ch) {
hasUpper = true
} else if unicode.IsDigit(ch) {
hasDigit = true
} else if strings.ContainsRune("!@#%^&*()-+", ch) {
hasSpecial = true
}
}

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

复杂度分析

  • 时间复杂度:O(n + |\Sigma|),其中 n 是字符串 password 的长度,\Sigma 是特殊字符的集合。

  • 空间复杂度:O(|\Sigma|),即为哈希表需要使用的空间。

 Comments
On this page
2299-强密码检验器 II