[leetcode]420强密码检验器,贪心

题意

用最少次数将一个密码变成强密码。
强密码的定义为:

  1. 长度为6到20
  2. 包含字母大小写与数字
  3. 同样的字符不能连续出现3次以及3次以上

思路

贪心,看着代码理解。
这里用的变量有点多,所以变量名随便一点。同时有些变量有复用的情况解释一下。

22行以上:
a,b,c表示数字、大写字母、小写字母是否缺失,1表示缺失,0表示存在,为1的时候就是需要添加该类型的字符,但强密码只要有不要多,所以贪心就是补充1个,
n表示password的字符个数,
j表示出现连续字符的连续长度
z 表示出现连续字符需要修改的字符个数,这里每连续3个修改一个字符就可以破坏连续。所以是j/3的累加。

22行以下:
a表示数字、大写字母、小写字母这三种类型的缺失个数,如password缺失大写字母与数字,
这里的a就会为2,a的意义就变成了需要在password上添加a个字符去补充类型。
n表示一种需要删除字符的个数的状态
j才是表示必须要删除的字符个数。

这道题需要分类讨论,
最简单的情况,字符个数不足6个的时候至少要补充到6个,即6-n,至少补充到有3种类型,即a,不用考虑连续个数,因为你的补充字符的操作是可以打断连续的,所以max(6-n,a);
然后就是长度在6到20之间的时候,这里不考虑删除,因为删除的效果只会小于等于修改,所以答案就是max(z,a)
最后是超过20的情况
这里添加的效果就会小于修改和删除,所以不用考虑添加的操作
因为要控制到长度在20以内,那么n-20个删除操作就是必不可少的,但删除了n-20个数字后,又会使得z中多少个字符不用去修改呢?
从26行后,n是个状态,j是必定会执行的删除操作
如果有个字符串的一个子串是baaab,这里可以看出aaa必定会令z加一,若不执行删除操作,必须进行修改一次,但如果进行过删除操作,且a被删除了一个,那这时候的z就应该减一。这是出发点。

aaaaa要修改1个字符,想不修改就要删除3个a
aaaaaa要修改2个字符,想不修改就要删除3个a,想要只修改1个字符就要删除1个a
aaaaaaaaa要修改3个字符,想不修改就要删除6个a,想要只修改2个字符就要删除1个a,想要只修改1个字符就要删除4个a。

多观察一下规律,不难发现就是和连续字符的长度的余数相关。对应代码中的x和y,有x段连续长度为3的倍数的话,优先删除这x段的最后1个字符,那么z就可以少修改x个字符,有y段连续长度为3的倍数+1的话,次优先删除这y段的最后2个字符,那么z就可以少修改y个字符,到最后还有剩余的n,z就可以少修改n/3个字符。

代码

class Solution {
public:
    int strongPasswordChecker(string password) {
        int i,j,a,b,c,n,x,y,z;
        a = b = c = 1;
        x = y = z = 0;
        n = password.size();
        for(i = 0;i < n;i ++){
            if(password[i]>='0'&&password[i]<='9')a = 0;
            else if(password[i]>='A'&&password[i]<='Z')b = 0;
            else if(password[i]>='a'&&password[i]<='z')c = 0;
            j = 1;
            while(i+1<n&&password[i]==password[i+1]){
                j ++;
                i ++;
            }
            if(j>2){
                z += j/3;
                if(j%3==0)x ++;
                else if(j%3==1)y ++;
            }
        }
        a = a+b+c;
        if(n<6)return max(6-n,a);
        else if(n<21) return max(z,a);
        n -= 20;
        j = n;
        if(n<=x)return max(z-n,a)+j;
        n-=x;
        z-=x;
        if(n<=2*y)return max(z-n/2,a)+j;
        n-=2*y;
        z-=y;
        return max(z-n/3,a)+j;
    }
};

版权声明:本文为weixin_57059105原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。