LeetCode 420. 强密码检验器题解

420. 强密码检验器题解

题目来源:420. 强密码检验器

2022.04.02 每日一题

LeetCode 题解持续更新中Github仓库地址 CSDN博客地址

今天的题目是一个Hard,我觉得可能是因为麻烦吧

对于这个密码,我们可以进行分类讨论

首先 定义 n 是 字符串的长度 ,定义变量 m 是字符串中字符的种类(大写字符,小写字符,数字)

首先判断字符串的长度,这个分为三类

  1. 长度小于6

    ​ 在这个范围之中,密码的长度不满足要求,如果遇到了连续三个的字符要进行删除操作,就需要有一个添加的操作,使得密码的长度满足要求。因此我们可以使用替换来代替这个操作,因此当长度小于6的时候,他的最少的操作次数就是max(6-n.3-m)

  2. 长度在6和20之间

    ​ 在这个范围之中,增加的操作是为了破坏连续三个子串或者增加字符的种类,而删除操作时为了破坏连续三个子串,这两个操作都可以使用替换进行操作,替换操作,如果遇到连续的字符串,每三个进行一次操作,从而得到的最少操作次数就是字符相差的个数与 将密码中所有的三个一样的字符删除的个数的最大值

  3. 长度大于20

    ​ 这种情况之下,如果进行一个添加操作就需要进行一次删除操作,从而保持密码字符串的长度与题目所说的要求相符合,因此可以使用 替换进行操作,为了使字符串的长度满足题目要求,我们应该首先删除 连续的三个字符在不考虑余数的情况下,每删除 33 个字符,能够连带的减少一次「替换」操作。因此我们可以根据 连续三个的字符串的个数对 3 取模进行统计,得到 cnts,最终的「替换」操作数 tot。除了可变的「替换」操作以外,我们不可避免还需要 base = n - 20base=n−20 的「删除」操作,最少操作次数可以归纳到 n-20+ max(tot, 3 - m)

    class Solution {
    public:
        int strongPasswordChecker(string password) {
            // 创建数组,统计各个类型的变量
            bool cnt[3];
            // 将密码字符串转换成为字符数组
            // 取得字符串的长度,后续由长度进行判断
            int n = password.length();
            // 遍历数组,统计各个类型是否存在
            for (int i = 0; i < n; i++) {
                if (password[i] <= 'z' && password[i] >= 'a') cnt[0] = true;
                else if (password[i] <= 'Z' && password[i] >= 'A') cnt[1] = true;
                else if (password[i] <= '9' && password[i] >= '0') cnt[2] = true;
            }
            // 创建变量 sum 统计各个类型的是否齐全
            int sum = 0;
            for (bool c : cnt) if (c) sum++;
            // 如果字符串的长度小于 6 ,就返回替换 和 添加的最大值
            if (n < 6) return max(6 - n, 3 - sum);
            if (n <= 20) {
                // 创建变量统计连续三个相同字符的个数(替换的个数)
                int tot = 0;
                // 统计相同字符的个数
                for (int i = 0; i < n; ) {
                    int j = i;
                    while (j < n && password[j] == password[i]) j++;
                    int c = j - i;
                    if (c >= 3) tot += c / 3;
                    i = j;
                }
                return max(tot, 3 - sum);
            }
            // 现在要讨论的是字符串的长度大于 20 的情况
            int tot = 0;
            int cnts[3];
            // 统计 3个连续字符的个数
            for (int i = 0; i < n; ) {
                int j = i;
                while (j < n && password[j] == password[i]) j++;
                int c = j - i;
                if (c >= 3) {
                    tot += c / 3;
                    cnts[c % 3]++;
                }
                i = j;
            }
            // 用变量 base 统计需要删除的字符个数
            int base = n - 20, cur = base;
            for (int i = 0; i < 3; i++) {
                if (i == 2) cnts[i] = tot;
                if (cnts[i] != 0 && cur != 0) {
                    int t = min(cnts[i] * (i + 1), cur);
                    cur -= t;
                    tot -= t / (i + 1);
                }
            }
            return base + max(tot, 3 - sum);
        }
    };
    
    class Solution {
        public int strongPasswordChecker(String password) {
            // 创建数组,统计各个类型的变量
            boolean[] cnt = new boolean[3];
            // 将密码字符串转换成为字符数组
            char[] a = password.toCharArray();
            // 取得字符串的长度,后续由长度进行判断
            int n = password.length();
            // 遍历数组,统计各个类型是否存在
            for (int i = 0; i < n; i++) {
                if (a[i] <= 'z' && a[i] >= 'a') cnt[0] = true;
                else if (a[i] <= 'Z' && a[i] >= 'A') cnt[1] = true;
                else if (a[i] <= '9' && a[i] >= '0') cnt[2] = true;
            }
            // 创建变量 sum 统计各个类型的是否齐全
            int sum = 0;
            for (boolean c : cnt) if (c) sum++;
            // 如果字符串的长度小于 6 ,就返回替换 和 添加的最大值
            if (n < 6) return Math.max(6 - n, 3 - sum);
            if (n <= 20) {
                // 创建变量统计连续三个相同字符的个数(替换的个数)
                int tot = 0;
                // 统计相同字符的个数
                for (int i = 0; i < n; ) {
                    int j = i;
                    while (j < n && a[j] == a[i]) j++;
                    int c = j - i;
                    if (c >= 3) tot += c / 3;
                    i = j;
                }
                return Math.max(tot, 3 - sum);
            }
            // 现在要讨论的是字符串的长度大于 20 的情况
            int tot = 0;
            int[] cnts = new int[3];
            // 统计 3个连续字符的个数
            for (int i = 0; i < n; ) {
                int j = i;
                while (j < n && a[j] == a[i]) j++;
                int c = j - i;
                if (c >= 3) {
                    tot += c / 3;
                    cnts[c % 3]++;
                }
                i = j;
            }
            // 用变量 base 统计需要删除的字符个数
            int base = n - 20, cur = base;
            for (int i = 0; i < 3; i++) {
                if (i == 2) cnts[i] = tot;
                if (cnts[i] != 0 && cur != 0) {
                    int t = Math.min(cnts[i] * (i + 1), cur);
                    cur -= t;
                    tot -= t / (i + 1);
                }
            }
            return base + Math.max(tot, 3 - sum);
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值