142 lines
4.2 KiB
Java
142 lines
4.2 KiB
Java
//
|
||
//如果一个密码满足下述所有条件,则认为这个密码是强密码:
|
||
//
|
||
//
|
||
// 由至少 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)
|
||
|
||
}
|