leet-code/src/main/java/leetcode/editor/cn/StrongPasswordChecker.java
2022-04-02 16:40:19 +08:00

142 lines
4.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
//如果一个密码满足下述所有条件,则认为这个密码是强密码:
//
//
// 由至少 6 个,至多 20 个字符组成。
// 至少包含 一个小写 字母,一个大写 字母,和 一个数字 。
// 同一字符 不能 连续出现三次 (比如 "...aaa..." 是不允许的, 但是 "...aa...a..." 如果满足其他条件也可以算是强密码)。
//
//
// 给你一个字符串 password ,返回 将 password 修改到满足强密码条件需要的最少修改步数。如果 password 已经是强密码,则返回 0
//。
//
// 在一步修改操作中,你可以:
//
//
// 插入一个字符到 password
// 从 password 中删除一个字符,或
// 用另一个字符来替换 password 中的某个字符。
//
//
//
//
// 示例 1
//
//
//输入password = "a"
//输出5
//
//
// 示例 2
//
//
//输入password = "aA1"
//输出3
//
//
// 示例 3
//
//
//输入password = "1337C0d3"
//输出0
//
//
//
//
// 提示:
//
//
// 1 <= password.length <= 50
// password 由字母、数字、点 '.' 或者感叹号 '!'
//
// Related Topics 贪心 字符串 堆(优先队列) 👍 138 👎 0
package leetcode.editor.cn;
//420:强密码检验器
public class StrongPasswordChecker {
public static void main(String[] args) {
Solution solution = new StrongPasswordChecker().new Solution();
// TO TEST
solution.strongPasswordChecker("aaa111");
}
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public int strongPasswordChecker(String password) {
char[] cs = password.toCharArray();
int n = cs.length;
// 计算字符种类
int A = 0, B = 0, C = 0;
for (char c : cs) {
if (c >= 'a' && c <= 'z') {
A = 1;
} else if (c >= '0' && c <= '9') {
B = 1;
} else if (c >= 'A' && c <= 'Z') {
C = 1;
}
}
int m = A + B + C;
// 情况1
if (n < 6) {
return Math.max(6 - n, 3 - m);
}
// 情况2
else if (n <= 20) {
// 需要替换的次数
int tot = 0;
// 采用双指针的方式求出超三连字符
for (int i = 0; i < n; ) {
int j = i;
while (j < n && cs[j] == cs[i]) {
j++;
}
int l = j - i;
if (l >= 3) {
tot += l / 3;
}
i = j;
}
return Math.max(tot, 3 - m);
} else {
int tot = 0;
int[] counts = new int[3];
for (int i = 0; i < n; ) {
int j = i;
while (j < n && cs[j] == cs[i]) {
j++;
}
int l = j - i;
// 同时统计 需要替换的次数 与 l%3
if (l >= 3) {
tot += l / 3;
counts[l % 3]++;
}
i = j;
}
// base不管怎么样都要删这么多次
int base = n - 20, cur = base;
for (int i = 0; i < 3; i++) {
// l%3==2 的情况因为l%3==0和l%3==0的情况在删去只会就会变成l%3==2同时每改一次等价于删除3次所以替代
if (i == 2) {
counts[i] = tot;
}
if (counts[i] != 0 && cur != 0) {
// 对于 l%3==i 的数来说, 要删的个数就是 counts[i] * (i + 1)
int t = Math.min(counts[i] * (i + 1), cur);
cur -= t;
// 每减少一个删去一个 i+1 ,都可以少修改一次
tot -= t / (i + 1);
}
}
return base + Math.max(tot, 3 - m);
}
}
}
//leetcode submit region end(Prohibit modification and deletion)
}