C语言 | Leetcode C语言题解之第420题强密码检验器

题目:

题解:

cpp 复制代码
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))

int strongPasswordChecker(char * password) {
    int n = strlen(password);
    bool has_lower = false, has_upper = false, has_digit = false;
    for (int i = 0; i < n; i++) {
        if (islower(password[i])) {
            has_lower = true;
        } else if (isupper(password[i])) {
            has_upper = true;
        } else if (isdigit(password[i])) {
            has_digit = true;
        }
    }
    int categories = has_lower + has_upper + has_digit;

    if (n < 6) {
        return MAX(6 - n, 3 - categories);
    } else if (n <= 20) {
        int replace = 0;
        int cnt = 0;
        char cur = '#';

        for (int i = 0; i < n; i++) {
            if (password[i] == cur) {
                ++cnt;
            } else {
                replace += cnt / 3;
                cnt = 1;
                cur = password[i];
            }
        }
        replace += cnt / 3;
        return MAX(replace, 3 - categories);
    } else {
        // 替换次数和删除次数
        int replace = 0, remove = n - 20;
        // k mod 3 = 1 的组数,即删除 2 个字符可以减少 1 次替换操作
        int rm2 = 0;
        int cnt = 0;
        char cur = '#';

        for (int i = 0; i < n; i++) {
            if (password[i] == cur) {
                ++cnt;
            } else {
                if (remove > 0 && cnt >= 3) {
                    if (cnt % 3 == 0) {
                        // 如果是 k % 3 = 0 的组,那么优先删除 1 个字符,减少 1 次替换操作
                        --remove;
                        --replace;
                    } else if (cnt % 3 == 1) {
                        // 如果是 k % 3 = 1 的组,那么存下来备用
                        ++rm2;
                    }
                    // k % 3 = 2 的组无需显式考虑
                }
                replace += cnt / 3;
                cnt = 1;
                cur = password[i];
            }
        }
        if (remove > 0 && cnt >= 3) {
            if (cnt % 3 == 0) {
                --remove;
                --replace;
            } else if (cnt % 3 == 1) {
                ++rm2;
            }
        }
        replace += cnt / 3;

        // 使用 k % 3 = 1 的组的数量,由剩余的替换次数、组数和剩余的删除次数共同决定
        int use2 = MIN(MIN(replace, rm2), remove / 2);
        replace -= use2;
        remove -= use2 * 2;
        // 由于每有一次替换次数就一定有 3 个连续相同的字符(k / 3 决定),因此这里可以直接计算出使用 k % 3 = 2 的组的数量
        int use3 = MIN(replace, remove / 3);
        replace -= use3;
        remove -= use3 * 3;
        return (n - 20) + MAX(replace, 3 - categories);
    }
}
相关推荐
SunnyByte5 小时前
C语言——贪吃蛇的实现
c语言·单链表·贪吃蛇
浅念-7 小时前
刷穿LeetCode:BFS 解决 Flood Fill 算法
数据结构·c++·算法·leetcode·职场和发展·bfs·宽度优先
im_AMBER9 小时前
手撕hot100之矩阵!看完这篇就AC~
javascript·数据结构·线性代数·算法·leetcode·矩阵
笨笨饿9 小时前
#79_NOP()嵌入式C语言中内联汇编宏的抽象封装模式研究
linux·c语言·网络·驱动开发·算法·硬件工程·个人开发
weixin_4217252610 小时前
C语言中volatile关键字怎么用C语言volatile在多线程中的作用
c语言·数据结构·运算符优先级·变量命名·volatile关键字
星河耀银海10 小时前
C语言与数据库交互:SQLite实战与数据持久化
c语言·数据库·sqlite·交互
沪漂阿龙11 小时前
程序员面试技术爆款文:2026大厂算法通关手册——从零基础到LeetCode刷穿,这一篇就够了
算法·leetcode·面试
05候补工程师11 小时前
【408 从零到一】线性表逻辑特征、存储结构对比与 C/C++ 动态内存分配避坑指南
c语言·开发语言·数据结构·c++·考研
傻瓜搬砖人12 小时前
第五章习题
c语言·谭浩强·绿皮书第三版
华清远见成都中心12 小时前
C 语言内存管理深度解析:malloc/free 与嵌入式堆栈分配策略
java·c语言·算法