题解 | #密码验证合格程序#

密码验证合格程序

http://www.nowcoder.com/practice/184edec193864f0985ad2684fbc86841

题目分析

  1. 题目给出我们若干条字符串,其含义是我们经常会注册登录所使用的密码
  2. 题目对密码格式进行要求
  • 第一点:密码必须超过8位
  • 第二点:必须有大写字母、小写字母、数字、符号四种中的三种
  • 第三点:密码不能有重复的公共子串,公共子串长度判定为3个字符及以上
  1. 我们要输出其是否符合以上条件的判断结果,OK或者NG
  • 思路
    • 对于第一点我们只要判断是否长度合法即可
    • 对于第二点我们可以准备要给列表分别表示四种情况的出现与否状态
      • 如果出现了对应类型的情况,则标记其值为1
      • 最后查看是否标记为1的种类满足三种的要求
    • 对于第三点是一个处理字符串的问题,我们分两种方法解决

方法一:暴力搜索

  • 实现思路
    • 我们知道如果有不满足第三点的情况,不管公共部分的子串有多长,至少会出现3个字符的子串同时出现两次及以上的情况

    • 因此我们遍历取出所有的3字符的子串,并且暴力在剩余部分字符串中检查搜索

    • 直到检查到其不会出现重复子串完全合法才输出OK

    • 否则输出NG

def check(pw):
    if len(pw) <= 8:			# 判断密码的长度
        return False
    
    checks = [0,0,0,0]			# 四种情况满足三种的辅助列表
    for c in pw:
        if c.isupper():			# 大写字母
            checks[0] = 1
        elif c.islower():		# 小写字母
            checks[1] = 1
        elif c.isdigit():		# 数字
            checks[2] = 1
        else:					# 其他字符
            checks[3] = 1
    if sum(checks) < 3:
        return False
        
    
    for i in range(len(pw) - 2):		# 循环遍历找到子字符串的起点
        if pw[i:i+3] in pw[i+3:]:		# 在剩下的字符串中顺序查找匹配当前字符串
            return False
    
    return True



while True:
    try:
        pw = input()
        if check(pw):
            print('OK')
        else:
            print('NG')
    except:
        break

复杂度分析

  • 时间复杂度:O(n2)O(n^2),由于对于公共子串的检查和搜索进行了两轮查找工作,时间代价为平方级别
  • 空间复杂度:O(1)O(1),只有一个校验题目第二点的时候用到了常量级别的checks列表

方法二:借助字典辅助查找

  • 实现思路
    • 暴力搜索的时间代价是平方级别的
    • 我们可以在遍历的过程中对于当前的未出现过的子字符串都存储在字典中
    • 在继续遍历的过程中直接根据字符串在字典中是否出现过来判断重复情况
    • 由于字典的组织形式是哈希表,因此大大减少了搜索时间的开销

alt


def check(pw):
    if len(pw) <= 8:			# 判断密码的长度
        return False
    
    checks = [0,0,0,0]			# 四种情况满足三种的辅助列表
    for c in pw:
        if c.isupper():			# 大写字母
            checks[0] = 1
        elif c.islower():		# 小写字母
            checks[1] = 1
        elif c.isdigit():		# 数字
            checks[2] = 1
        else:					# 其他字符
            checks[3] = 1
    if sum(checks) < 3:
        return False
        
    dc = {}
    for i in range(len(pw) - 2):		# 遍历所有的子字符串起点
        if pw[i:i+3] in dc:				# 在字典中搜索
            return False
        else:							# 如果未曾经出现过则加入字典中,等待之后的判定
            dc[pw[i:i+3]] = 1
    
    return True



while True:
    try:
        pw = input()
        if check(pw):
            print('OK')
        else:
            print('NG')
    except:
        break

复杂度分析

  • 时间复杂度:O(n)O(n),只需要一次遍历字符串的时间代价
  • 空间复杂度:O(n)O(n),借助了字典空间代价,存储字符串的空间大小的开销
不会做题写的题解 文章被收录于专栏

哎呀我好笨呀,一不小心又不会了一道题

全部评论
想和你讨论一下~检查子字符串时,如果使用“if pw[i:i+3] in pw[i+1:]“,那么两个子字符串可能重复使用了同一个字符。比如密码串'121212ABC',每次检查3个字符时,会把‘121’加入到可能重复的选项中,在检测以下标为2开头的3个字符子串时,又遇见‘121’,程序会认为这是错误的,但实际上真实重复的字符串并非‘121’而是‘12’,不应该判错。所以这里我觉得判断条件应该是”if pw[i:i+3] in pw[i+3:]“,不知道你怎么认为呢?
6 回复 分享
发布于 2021-12-02 02:59
md,每次做题都感觉题目说的不明不白的。什么叫字串,第1,3,7位字符组成的字符串算不算?如果算,那第一个显然有很多种方式提取出三个0的字串,应该输出NG,结果答案不是。另外所谓公共元素,又在指什么,什么叫两个包含公共元素的字串重复,如果字串没有公告元素,那字串怎么可能重复?这tm就不知道是说的啥。
4 回复 分享
发布于 2023-05-13 11:40 四川
大佬 你这没有处理为空的时候的情况,如果中间有个空格 这个就有问题了
1 回复 分享
发布于 2022-03-09 10:49
这样用字典还有set的那AAAAabc123不就报错了嘛
1 回复 分享
发布于 2022-03-20 20:20
islower()不是全部小写才true吗
点赞 回复 分享
发布于 2022-01-29 00:05
有循环
点赞 回复 分享
发布于 2022-02-14 15:12
放列表就行了,不用放字典啊
点赞 回复 分享
发布于 2022-02-22 16:59
没必要用字典,用set就可以了
点赞 回复 分享
发布于 2022-03-16 21:32
为什么要加try,except,是会有什么异常吗
点赞 回复 分享
发布于 2022-03-16 22:45
第一中方法如果是'aba’这种如果重复了应该也被计算成不符合的了,按照题意应该是OK的 比如'~!+8+*fQO%&(2974)W9~D6X60T5%@1V1961*&+8+!046F#q#+S' 这个串应该是OK的但是答案确实NG的 对于‘+8+’字符串里重复了,但是它本身不是有重复的+号吗应该算合格的啊,搞不懂这里了 问题在于‘aab’这种重复出现到底算不算合格?
点赞 回复 分享
发布于 2022-03-30 18:22
第三条真没看懂
点赞 回复 分享
发布于 2023-05-31 15:46 广东
请问,其他符号不能够包含空格和换行好像这里没处理呀
点赞 回复 分享
发布于 昨天 16:18 广东

相关推荐

object3:开始给部分🌸孝子上人生第一课了
点赞 评论 收藏
分享
头像
11-18 16:08
福州大学 Java
影流之主:干10年不被裁,我就能拿别人一年的钱了,日子有盼头了
点赞 评论 收藏
分享
102 17 评论
分享
牛客网
牛客企业服务