第十五届蓝桥杯大赛软件赛国赛Python 大学 C 组试做【本期题单: 设置密码、栈】

早上好啊大伙,这一期依旧是蓝桥杯备赛刷题的记录。

本期题单:设置密码、栈

前言

前段时间准备省赛,运气好进国赛了。所以就开始准备6月份的国赛。但是近期还有别的比赛要准备,所以刷题的速度比较慢,可能每一期就会有一两道题目。

如果大伙再刷哪道题的时候遇到问题了,也可以留言或者私信,小白兔会去先尝试一下那到题目。

文章目录

设置密码

题目

题目链接:设置密码


思路分析

这道题需要去判断的有四点:

  1. 是否只包含 字母、数字、指定的特殊字符
  2. 字符串长度
  3. 大写字母、小写字母、数字、特殊字符所包含类别数目
  4. 特殊字符种类数

对于第一点,比较麻烦的就是特殊字符,可以将特殊字符用列表存起来,然后用 in 来判断。

第二点就直接用 len() 就行了。

第三点 和 第四点可以用哈希,然后最后用 count 来数。

代码

python 复制代码
x = [126, 33, 64, 35, 36, 37, 94, 38, 42, 40, 41, 95]  # 定义允许的特殊字符的ASCII码列表(包括!@#$%^&*()_等)

def isture(s):  # 定义函数:检查字符串是否只包含允许的字符
    for i in s:  # 遍历字符串中的每个字符
        if not (ord(i) in x or i.isdigit() or i.isalpha()):  # 检查字符是否满足条件:
            # ord(i)获取字符ASCII码,判断是否在x列表中(特殊字符),或是否为数字/字母
            return False  # 若不满足条件,返回False
    return True  # 所有字符均满足条件,返回True

def count(s):  # 定义函数:统计字符串的字符类型数量和特殊字符种类
    cnt1 = [0, 0, 0, 0]  # 初始化cnt1列表,用于记录是否包含大写字母、小写字母、数字、其他字符(存在则记为1)
    cnt2 = [0 for _ in range(130)]  # 初始化cnt2列表,索引为ASCII码,记录每种特殊字符的出现次数(非0表示存在)
    for i in s:  # 遍历字符串中的每个字符
        if i.isupper():  # 判断是否为大写字母
            cnt1[0] = 1  # 标记存在大写字母
        elif i.islower():  # 判断是否为小写字母
            cnt1[1] = 1  # 标记存在小写字母
        elif i.isdigit():  # 判断是否为数字
            cnt1[2] = 1  # 标记存在数字
        else:  # 其他字符(特殊字符)
            cnt1[3] = 1  # 标记存在特殊字符
            cnt2[ord(i)] = 1  # 在cnt2中标记该特殊字符的ASCII码位置为1(存在)
    return (cnt1.count(1), cnt2.count(1))  # 返回两个统计值:
    # cnt1.count(1):字符类型数量(大写/小写/数字/特殊中存在的类型数)
    # cnt2.count(1):不同特殊字符的种类数(ASCII码在0-129范围内的特殊字符数量)

n = int(input())  # 读取输入的测试用例数量
for _ in range(n):  # 遍历每个测试用例
    s = input()  # 读取输入的字符串
    if isture(s):  # 检查字符串是否为合法字符(仅包含字母、数字、指定特殊字符)
        c1, c2 = count(s)  # 调用count函数获取字符类型数和特殊字符种类数
        Len = len(s)  # 获取字符串长度
        # 以下为密码强度判断逻辑
        if Len >= 12 and (c1 >= 3 and c2 >= 3 or c1 >= 4):  # 强度等级3条件:
            # 长度≥12,且(字符类型≥3且特殊字符种类≥3,或字符类型≥4)
            print(3)  # 输出强度等级3
        elif Len >= 8 and c1 >= 2:  # 强度等级2条件:长度≥8且字符类型≥2
            print(2)  # 输出强度等级2
        elif Len >= 6:  # 强度等级1条件:长度≥6(隐含字符类型可能不足2,但至少满足长度)
            print(1)  # 输出强度等级1
        else:  # 长度<6
            print(0)  # 输出强度等级0
    else:  # 字符串包含不允许的字符
        print(0)  # 输出强度等级0

题目

题目链接:

思路分析

直接按照题目的意思来写,就是下面这个步骤 ------

  1. 判断这个数在不在列表里,在的话,删除原本的数
  2. 计算相邻两个数和是否为奇数

按照原本的意思,每次变化都需要重新计算奇数数量。但是显然这样会超时。

那么我们就需要优化一下,首先能否不去重新计算奇数?

当这个数不在列表中的时候,我们直接判断最后两个数的情况,进行修改即可。

如果它在列表中的时候,我们就需要找到原本它所在的位置,然后处理它的邻里关系。例如说:

1, 2,3,4,5中我们需要修删掉2。

那么我们要判断 1和2 ,2和3,这是原本这个位置的奇数关系,如果是奇数就需要把他们减掉,例如说现在就需要 - 2。然后去掉2之后,1和3也需要判断,例如说现在就不用变。

再然后,我们还需要判断存在的数的位置是不是开头或者结尾。

下面看代码

python 复制代码
import os
import sys

# 请在此输入您的代码
n = int(input())
cnt = 0
lst = [int(input())]
print(0)
for i in range(1, n):
    x = int(input())
    if x in lst:
        p = lst.index(x)
        if p > 0 and (lst[p-1] + x) % 2 == 1:
            cnt -= 1
        if p < len(lst) - 1 and (lst[p+1] + x) % 2 == 1:
            cnt -= 1
        if p > 0 and p < len(lst) - 1 and (lst[p-1] + lst[p+1]) % 2 == 1:
            cnt += 1
        lst.remove(x)
    lst.append(x)
    if (lst[-2] + x) % 2 == 1:
        cnt += 1
    print(cnt)

但是,这个代码只能过70%,有6条还是会超时。

那么再修改一下思路,我们再看看第一条中能不能优化。

判断是否存在新输入的数,以及寻找这个数的位置。

题目并不怎么强调整条列表的每个数的位置,更注重一个数及其两边的数的关系。

那么我们就可以用哈希的方式来寻找,大家可否想到字典这个哈希结构。

我们将这个数作为key,然后两侧的值作为value

删除数据时,可以直接找到这个数及其两侧的值,然后仿照上面的写法就行。

然后这个写法给大伙提醒一些需要注意的点:

  1. 记得将 0 也进行定义。
  2. 对于新输入的数要用 [a, 0]来定义。
  3. 对于上一个数就是重复数,要特别注意

OK,根据上面的提示和思路,整体和链表比较像只是用字典来实现了,大伙可以试试,然后再看下面的代码

代码

python 复制代码
import os
import sys

n = int(input())  # 读取插入操作的次数
cnt = 0  # 初始化奇数对计数
l_x = int(input())  # 读取第一个节点的值
dic = {0:[0,0], l_x:[0,0]}  # 初始化字典,0作为哨兵节点,l_x作为第一个节点
print(0)  # 第一个节点插入后,没有相邻节点,输出0

for i in range(1, n):
    x = int(input())  # 读取新插入的节点值
    
    # 处理节点已存在的情况(删除操作)
    if x in dic.keys():
        l, r = dic[x][0], dic[x][1]  # 获取当前节点的前驱和后继
        if l != 0 and (x + l) % 2 == 1:  # 如果前驱存在且和为奇数,减少计数
            cnt -= 1
        if r != 0 and (x + r) % 2 == 1:  # 如果后继存在且和为奇数,减少计数
            cnt -= 1
        if l != 0 and r != 0 and (l + r) % 2 == 1:  # 如果前驱和后继存在且和为奇数,增加计数
            cnt += 1
        dic[r][0], dic[l][1] = l, r  # 更新前驱和后继的指针,跳过当前节点
        if r == 0:  # 如果当前节点是链表尾部,更新l_x为前驱
            l_x = l
    
    # 插入新节点到链表尾部
    dic[x] = [l_x, 0]  # 新节点的前驱为l_x,后继为0
    dic[l_x][1] = x  # 更新l_x的后继为新节点
    if (x + l_x) % 2 == 1:  # 如果新节点与前驱的和为奇数,增加计数
        cnt += 1
    l_x = x  # 更新l_x为新节点,使其成为新的链表尾部
    print(cnt)  # 输出当前奇数对的数量

感谢大伙观看,别忘了三连支持一下

大家也可以关注一下我的其它专栏,同样精彩喔~

下期见咯~

相关推荐
databook11 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar12 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805112 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_12 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
数据智能老司机19 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机20 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机20 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机20 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i20 小时前
drf初步梳理
python·django
每日AI新事件20 小时前
python的异步函数
python