【leetCode】强密码检验器

问题描述
在这里插入图片描述
思路:
按照原字符串的顺序用字典法创建字典,键值为连着的该元素的个数。
1、首先检测是否有需要添加的数据类型和是否有需要增加或减去字符。
创建完字典后先判断是否有三个以上连续的值,有要通过插入元素来分离,3个需要1个,4个需要一个,5个需要两个,6个需要两个,7个需要3个,方法为n/2-1+n%2
如果是更换元素 3-1 4-1 5-1 6-2 7-2 那他需要的次数为n/3

对于这道题来说删除、插入、替换的顺序很重要。
先说说题解的方法。
大问题分小问题,
根据字符的长度可以分为三种:1、长度小于6的时候。2、长度小于等于20大于等于6的时候3、长度大于20的时候
第一种可能性长度小于6的时候:他只有两种更改方法:第一种是替换,第二种是插入,且连续字符长度为5,替换更改连续字符的方法最多只需要替换一次。
所以它的结果只需要考虑插入元素补长度和替换种类里的大者就可以。
**第二种可能性,**没有删除没有插入,只有替换。
直接替换步数就等于处理连续字替换数和缺失类型替换数取大者
第三种可能性,是最繁琐的因为它混入了删除,所以他需要考虑替换的连续组的连续数 %32 -> 连续数%31 -> 连续数%30,然后处理多余字符,删除的优先级是连续组的连续数 %30 -> 连续数%31 -> 连续数%32。这个删除的次数,不能一次用完,因为如果余数为0,他就只需要删除一次就可以减少一次替换数。而余数为1,它就需要减少两次减少一次替换数。
这是题解的代码理解一下。

class Solution:
    def strongPasswordChecker(self, password: str) -> int:
        n = len(password)       #密码长度
        has_lower = has_upper = has_digit = False       #用于看看3种情况是否都有
        for ch in password:     #用各种判断函数来判断是否有这几种符号
            if ch.islower():
                has_lower = True
            elif ch.isupper():
                has_upper = True
            elif ch.isdigit():
                has_digit = True


        categories = has_lower + has_upper + has_digit     #种类


        if n < 6:       #如果字符串长度小于6,就是要增加字符个数,和要添加种类的大者
            return max(6 - n, 3 - categories)
        elif n <= 20:   #长度在6-20,不需要删除操作 只需要只会出现增加种类和去除重复值两种可能,去除重复值最高效的也是修改
            replace = cnt = 0
            cur = "#"


            for ch in password:
                if ch == cur:
                    cnt += 1
                else:
                    replace += cnt // 3
                    cnt = 1
                    cur = ch


            replace += cnt // 3
            return max(replace, 3 - categories)
        else:       #有三种,删除多余值、增加数据种类还有去除连续值
            # 替换次数和删除次数
            replace, remove = 0, n - 20
            # k mod 3 = 1 的组数,即删除 2 个字符可以减少 1 次替换操作
            rm2 = cnt = 0
            cur = "#"   #当前字符


            for ch in password:
                if ch == cur:
                    cnt += 1    #当前字符连续次数
                else:
                    if remove > 0 and cnt >= 3:
                        if cnt % 3 == 0:
                            # 如果是 k % 3 = 0 的组,那么优先删除 1 个字符,减少 1 次替换操作
                            remove -= 1
                            replace -= 1
                        elif cnt % 3 == 1:
                            # 如果是 k % 3 = 1 的组,那么存下来备用
                            rm2 += 1    #记录余数为1的数组
                        # k % 3 = 2 的组无需显式考虑
                    replace += cnt // 3 #所有的重复数都用替换处理,上面是提前减1,所以他这里余数为1的情况是不用dlt处理的
                    cnt = 1
                    cur = ch


            if remove > 0 and cnt >= 3: #用于处理当连续字符在最后的时候
                if cnt % 3 == 0:
                    remove -= 1
                    replace -= 1
                elif cnt % 3 == 1:
                    rm2 += 1


            replace += cnt // 3


            # 使用 k % 3 = 1 的组的数量,由剩余的替换次数、组数和剩余的删除次数共同决定
            use2 = min(replace, rm2, remove // 2)
            replace -= use2
            remove -= use2 * 2
            # 由于每有一次替换次数就一定有 3 个连续相同的字符(k / 3 决定),因此这里可以直接计算出使用 k % 3 = 2 的组的数量
            use3 = min(replace, remove // 3)
            replace -= use3
            remove -= use3 * 3
            return (n - 20) + max(replace, 3 - categories)
strs = "aaaaAAAAAA000000123456"
a = Solution().strongPasswordChecker(strs)
print(a)

而我的代码!很繁琐,但是是我的想法。
有兴趣的可以理解 很垃圾- -

class Solution:
    def strongPasswordChecker(self, password: str) -> int:
        insert = 0      #记录需要插入的次数
        dlt = 0         #记录需要删除的次数
        alter = 0       #记录需要改变的次数,这里是种类
        mod_dlt = 0     #结果中需要删除的次数
        mod_alter = 0   #结果中需要改变的次数,种类
        mod_insert=0    #结果中需要插入的次数
        modify = 0      #结果中需要用修改来解决连续字符的次数
        length = len(password)
        flag = [False,False,False]  #用来判断三种字符是否都有
        if length<6:
            insert = 6-length
        elif length>20:
            dlt = length - 20
        for i in range(0,length):
            if password[i]>='a' and password[i]<='z':
                if flag[0] == False:
                    flag[0] = True
            elif password[i] >= 'A' and password[i] <= 'Z':
                if flag[1] == False:
                    flag[1] = True
            elif password[i]>='0' and password[i]<='9':
                if flag[2] == False:
                    flag[2] = True
            if flag == [True,True,True]:
                break
        alter = flag.count(False)
        if alter >0 and  insert >alter:
            insert -= alter
        elif alter >0 and insert>0:
            alter -=insert
        rm2 = 0
        cur = 0
        for i in range(0,length):
            if i==0:
                cur=1
            elif password[i] == password[i-1]:
                cur+=1
            elif password[i]!=password[i-1]:
                if cur >= 3:
                    if dlt>0 and cur%3==0:
                        mod_dlt+=1
                        dlt-=1
                        cur -=1
                    elif dlt>0 and cur%3==1:
                        rm2+=1


                    if cur>=3:
                        if insert>0:
                            t = int(cur/2-1+cur%2)
                            if t<=insert:
                                insert -=t
                                mod_insert += t
                                cur -= t*2
                            else:
                                cur -= insert * 2
                                mod_insert += insert
                                insert = 0
                        if cur>=3:
                            if alter>0:
                                t = int(cur/3)
                                if t <= alter:
                                    cur -= t * 3
                                    mod_alter += t
                                    alter -=t
                                else:
                                    mod_alter += alter
                                    cur = cur - alter * 3
                                    alter =0


                modify+=int(cur/3)
                cur =1
        if cur >= 3:
            if dlt > 0 and cur % 3 == 0:
                mod_dlt += 1
                dlt -= 1
                cur -= 1
            elif dlt > 0 and cur % 3 == 1:
                rm2 += 1
            if cur >= 3:
                if insert > 0:
                    t = int(cur / 2 - 1 + cur % 2)
                    if t <= insert:
                        insert -= t
                        mod_insert += t
                        cur -= t * 2
                    else:
                        cur -= insert * 2
                        mod_insert += insert
                        insert = 0
                if cur >= 3:
                    if alter > 0:
                        t = int(cur / 3)
                        if t <= alter:
                            cur -= t * 3
                            mod_alter += t
                            alter -= t
                        else:
                            mod_alter += alter
                            cur = cur - alter * 3
                            alter = 0


        modify += int(cur / 3)
        cur = 1
        use2 = min(modify, rm2, dlt // 2)
        modify -= use2
        mod_dlt+=use2*2
        dlt -= use2*2
        use3 = min(modify,  dlt // 3)
        modify -= use3
        mod_dlt+=use3*3
        dlt -= use3*3
        return int(modify+mod_alter+mod_dlt+mod_insert+dlt+insert+alter)


strs = "aaaabbbbccccddeeddeeddeedd"
a = Solution().strongPasswordChecker(strs)
print(a)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值