2024.9.6 Python,华为笔试题总结,字符串格式化,字符串操作,广度优先搜索解决公司组织绩效互评问题,无向图

1.字符串格式化

name = "Alice"
age = 30
formatted_string = "Name: {}, Age: {}".format(name, age)
print(formatted_string)

或者

name = "Alice"
age = 30
formatted_string = f"Name: {name}, Age: {age}"
print(formatted_string)

2.网络健康检查

第一行有两个整数m,n 接下来有n行字符串express
接下来m行,每行均有两个字符串,key和valve,
表达式中仅会出现AND,OR,(、),’,空格,=,子段名,数据(单引号内部),给出的表达式一定是有效的,AND的优先级高于OR
=左侧为字段名
右侧为数据,类型为字符串
0表示健康,1表示不健康
样例:
输入:2 2
error = ‘0’ AND (name = ‘NE40’ OR name = ‘NE20’)
error = ‘1’ AND (name = ‘NE40’ OR name = ‘NE20’)
name NE40
error 0
输出:
0
1
输入:
3 2
error = ‘1’ AND (name = ‘NE40’ OR name = ‘NE20’)
error = ‘2’ AND (name = ‘NE40’ OR name = ‘NE20’)
error = ‘3’ AND (name = ‘NE40’ OR name = ‘NE20’)
name NE40
error 3
这个的输出应该是:
1
1
0
这个第二个样例的解释是:
对于条件error = ‘1’ AND (name = ‘NE40’ OR name = ‘NE20’)
当name取值为NE40,error取值为3时,表达式计算结果为false所以输出1,表示不健康

题目分析:
这个题就抽象,我直到现在才看懂这个题在干嘛,这个题的意思是,以第一个题为例。name就是NE40这个东西,然后呢带入第一个式子,括号里就可以写出一个布尔式了对吧,然后第二个error 0带入式子左边,如果左右两边相同那么就是这个式子正确的,所以输出0,那么就输出1。
代码如下:

def func(m, n, expressions, variables):
    # 创建键值对字典
    key_val_dict = {key: valve for key, valve in variables}
    results = []

    def evaluate_expression(expression):
        # 替换表达式中的字段名为对应的数据
        for key, valve in key_val_dict.items():
            # 替换表达式的等式部分
            expression = expression.replace(f"{key} = '", f"'{valve}' == '")
        
        # 替换 AND 和 OR 为 Python 的逻辑运算符
        expression = expression.replace("AND", "and").replace("OR", "or")
        
        # 确保括号格式正确
        expression = expression.replace("(", " ( ").replace(")", " ) ")
        
        # 评估表达式并返回布尔值
        return eval(expression)

    # 计算并存储每个表达式的结果
    for expr in expressions:
        result = evaluate_expression(expr)
        # 如果表达式为真,则健康,输出0;否则输出1
        results.append(1 if not result else 0)

    return results

if __name__ == '__main__':
    # 从标准输入读取 m 和 n
    m, n = map(int, input().split())  # 读取 m 行表达式和 n 行键值对
    
    # 读取 m 行表达式
    expressions = []
    for _ in range(m):
        expr = input().strip()
        expressions.append(expr)
    
    # 读取 n 行键值对
    variables = []
    for _ in range(n):
        var = input().split()  # 每行一个键值对,键与值之间用空格分隔
        variables.append(var)
    
    # 调用 func 函数并获取结果
    output = func(m, n, expressions, variables)
    
    # 输出结果
    for result in output:
        print(result)

代码逻辑:
1.代码总体的逻辑是直接把表达式expressions直接变成判断的对象,我不知道C++中是如何考虑这个问题的,但是在python中,这个东西其实非常的方便,这个题的难点在于如何把题目中的奇奇怪怪的对象变成我们熟悉的部分我们熟悉的东西。
2.先从if 开始,代码从这里起始,接下来我会详细的讲解m, n = map(int, input().split()) 这一句,因为对我而言,我更多的是使用class Solution这种形式,我很少使用input这种操作,所以我对这个东西非常的陌生。
(1)input()这个函数,如果我输入2,那他可以直接赋值给一个字母,但是这里他输入是2 3 中间这个空格出现以后这就变成了一个字符串,所以就需要通过字符串来去操作
(2)split()是一个方法,可以将输入的字符串按空格分割成一个列表此时的数据类型应该是[‘2’, ‘3’]
(3)map() 函数会将第一个参数 int 应用于 split() 返回的列表中的每个元素,即将字符串 ‘2’ 和 ‘3’ 转换为整数。此时的数据类型应该是[2,3]然后这个时候赋值就好了。
3.定义表达式expressions,.strip():去掉输入字符串前后的任何空白字符(例如空格或换行符),确保输入的表达式没有多余的空白。存好后,expressions中现在是m项列表
4.定义变量variables,和开始的input一样,中间通过空格分开
输入:
name NE40 error 3
存入的variables:
[
[‘name’, ‘NE40’],
[‘error’, ‘3’]
]
5.key_val_dict = {key: valve for key, valve in variables},把variables里的变量写一个字典,也可以用循环来写这个代码。
6.for key, valve in key_val_dict.items(): 这句必须用item不能用enumerate,enumerate单独指下标和元素,多用于列表,对于字典就是item方法来遍历所有元素。这里为什么要遍历字典而不是expression里的元素呢,你去读expressions里的元素去和字典匹配非常的难,那还不如去遍历字典,来replace expressions里的元素。
7.expression = expression.replace(f"{key} = ‘“, f”’{valve}’ == '“)
f”{key} = '":这是 f 字符串,用于动态插入变量的值。
{key} 是一个变量,占位符会被其值替换。
= ’ 这一部分是字符串中的固定字符,表示字段名后跟 =,然后是一个 单引号 ',用于表示字符串值的开始。
例如,如果 key 是 ‘name’,那么这部分字符串会变成:“name = '”。

f"‘{valve}’ == '":

这是另一个 f 字符串,其中嵌入了变量 valve。
‘{valve}’:变量 valve 的值被插入,并且这个值用单引号 ’ 包裹。单引号是 Python 字符串中的一部分,用来表示该变量的值是一个字符串。
== ':紧接着的 == ’ 是普通的字符串,用来表示逻辑表达式中等于的部分,并且最后加了一个单引号 ’ 来关闭之前打开的单引号。
例如,如果 valve 是 ‘NE40’,那么这一部分会变成:“‘NE40’ == '”。

8.return eval(expression)给出最终结果

3.公司组织绩效互评

为了避免有同学或者团队打高分,需要将员工分成两组进行打分。给定一个整数n和一个数组GoodRelationShips[][],其中,n表示人数,数组GoodRelationShips[][]是一个邻接表,GoodRelationShips[i]的元素[a,b,c]代表员工i和员工a,b,c是同学
请将这n个人分成两组,使其每一组不再有同学或者同团队的人
GoodRelationShips[i]不会包含i或者有重复的值,GoodRelationShips[i]中元素范围不超过GoodRelationShips.length-1
输入:数组形式的员工关系邻进表,第一行数字代表有N个顶点。顶点编号从0开始后续接N行。第i行代表第i-1个顶点和他有关系的同学的顶点编号
输出:分组方案按照节点编号排序,如果两个方案第一个节点相同,按照第二个节点排序,以此类推,如果无法分成符合的两组,那么输出-1
如输出如下两种方案时,选择第一种方案,因为方案一的分组2第一个节点编号更低:
分组1:1
分组2:2 3 4 5
和分组1:1 2
分组2: 3 4 5
如输出如下两种方案时,选择第二种方案,因为方案二的分组2的第一个节点编号更低:
分组1:1 2
分组2:3 4 5

分组1:1 3
分组2:2 4 5
样例:
输入:
4
1 3
0 2
1 3
0 2
输出:
0 2
1 3
样例2:
输入:
4
1 2 3
0 2
0 1 3
0 2
输出:
-1

def func(n, GoodRelationShips):
    from collections import deque, defaultdict

    # 构建邻接表
    graph = defaultdict(list)
    for i, neighbors in enumerate(GoodRelationShips):
        for neighbor in neighbors:
            graph[i].append(neighbor)
            graph[neighbor].append(i)  # 1.无向图

    # 二分图检测
    color = [-1] * n  # -1: 未着色, 0: 颜色0, 1: 颜色1

    def bfs(start):  #3.
        queue = deque([start])
        color[start] = 0 #4.
        while queue:
            node = queue.popleft()
            current_color = color[node]
            next_color = 1 - current_color
            for neighbor in graph[node]:
                if color[neighbor] == -1:  # 未着色
                    color[neighbor] = next_color
                    queue.append(neighbor)
                elif color[neighbor] == current_color:  # 颜色冲突
                    return False
        return True

    # 遍历所有节点,处理可能的非连通图
    for i in range(n):
        if color[i] == -1 and not bfs(i): #5.
            return [-1]

    # 提取结果
    group1 = [i for i in range(n) if color[i] == 0]
    group2 = [i for i in range(n) if color[i] == 1]#6.

    # 输出结果
    group1.sort()
    group2.sort()  #7.
    
    return [group1, group2] 

if __name__ == '__main__':
    import sys
    input = sys.stdin.read
    data = input().strip().split('\n')

    n = int(data[0])
    GoodRelationShips = [list(map(int, line.split())) for line in data[1:]]

    result = func(n, GoodRelationShips)
    
    if result == [-1]:
        print(-1)
    else:
        for group in result:
            print(" ".join(map(str, group)))  # 确保每个数字之间有空格

1.构建无向图的过程中,他相互append的时候并不会对别的值产生影响。也就是说,如果这个键对应的值里已经有这个值了,那么再次append便不会添加。
2.给color定义其实是给每一个人发一个标签
3.广度优先搜索第一个把0带入,在之后的循环中要把每个人带一次进去。0带入以后,进queue,然后给0的颜色置0,从队列里pop一个值出来,先问下这个值的颜色是什么,再问问他的对面是什么,读这个值的好友都有谁,遍历当前值的好友,如果他的好友没有染色,那么就给他染上对面的颜色,同时把他的好友加入queue里,再次循环。
4.我最开始以为这个循环有点糟糕,我是这样想的,就这个代码中,我现在假设,graph[0]=1,graph[1]=0,那么,现在bfs(0)的时候,我把代号0的颜色变成颜色0了,此时的代号1的颜色为-1,因为是-1,所以我要把他变成0的相反的颜色,那就是颜色1,对吧,那么此时把代号1添加进队列了,他的好友代号0已经染色了,所以while循环结束了,那么此时,i增加了,bfs(1)带入了,此时的bfs(1)进入以后第一件事是代号1染色为颜色0了,此时进for循环,代号0的颜色还没有改变,此时color[neighbor]==当前代号1的颜色0了,就输出-1了,这不就错误了吗,我的想法是,给这个bfs的代码第一行就写到,如果这个节点是-1再进这个函数,如果他染了色了,直接退出就好了。
5.然后你看,if条件里有这么一句。if color[i] = = -1 and not bfs(i):从前往后读他就是在做这个事情,所以如果这个节点染色了,他根本就进不了bfs
6.按需入库,i for i in range(n) if … 遍历i,满足条件入库,不满足跳过。
7.给group排序。
8.返回之后就没啥好说的了。

  • 52
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值