LeetCode 热题 HOT 100 (034/100)【宇宙最简单版】

【广度优先搜索】No. 0399 除法求值【中等】👉力扣对应题目指路

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
欢迎关注、订阅专栏 【力扣详解】谢谢你的支持!

题目描述:给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi = values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。另有一些以数组 queries 表示的问题,其中 queries[j] = [Cj, Dj] 表示第 j 个问题,请你根据已知条件找出 Cj / Dj = ? 的结果作为答案。

  • 返回 所有问题的答案 。如果存在某个无法确定的答案,则用 -1.0 替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用 -1.0 替代这个答案。

  • 注意:输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。

  • 注意:未在等式列表中出现的变量是未定义的,因此无法确定它们的答案。

  • 示例 1:

    输入:equations = [[“a”,“b”],[“b”,“c”]], values = [2.0,3.0], queries = [[“a”,“c”],[“b”,“a”],[“a”,“e”],[“a”,“a”],[“x”,“x”]]
    输出:[6.00000,0.50000,-1.00000,1.00000,-1.00000]
    解释:
    条件:a / b = 2.0, b / c = 3.0
    问题:a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
    结果:[6.0, 0.5, -1.0, 1.0, -1.0 ]
    注意:x 是未定义的 => -1.0

🔥 思路:【广度优先搜索】将变量转为节点,除法转为带权重的有向边

  • 那么对于 queries[j] = [Cj, Dj],也就是找 C_jD_j 的路径并累乘路径涉及到的边

参考如上思路,给出详细步骤如下:

  • 步骤一⭐生成图:双层哈希表【一个大哈希表 (key: node, value: node 对应的邻居哈希表),存储每个节点对应的邻居哈希表 (key: 邻居 node, value: node / 邻居 node 的值)】
    • 遍历 equationsvalues 中的每一项,提取 (s, e) 和对应的 v
    • 初始 s、e 的邻节点的哈希表
    • 根据当前遍历到的 equation 填充 s、e 的邻节点的哈希表【构建4条边】
  • 步骤二⭐搜索图:广度优先搜索
    • 初始化用于广度优先搜索的队列 queue
      • 队列中的每一项为 🍅 搜索过的节点及对到 该节点所得到的权重积 mul
    • 初始化结果答案列表 ans:初始都为 -1 表示未定义
    • 遍历 queries 中的每一项:寻找从起点到终点的最短路径,并计算权重积
class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        # ---------------------------------------------------------- step 1
        graph = {}  
        for (s, e), v in zip(equations, values):  # --------------- step 1.1
            # ----------------------------------------------------- step 1.2
            if s not in graph:
                graph[s] = {}   # 初始 s 的邻节点的哈希表
            if e not in graph:
                graph[e] = {}   # 初始 e 的邻节点的哈希表
            # ----------------------------------------------------- step 1.3    
            graph[s][e] = v     # s -> e,  权重为 v,	表示 s / e = v
            graph[e][s] = 1 / v # e -> s,	权重为 1/v,	表示 e / s = 1/v
            graph[s][s] = 1.0   # s -> s, 	权重为 1,	表示 s / s = 1
            graph[e][e] = 1.0	# e -> e, 	权重为 1,	表示 e / e = 1
        
        # ---------------------------------------------------------- step 2
        queue = []  # -------------------------------------------- step 2.1
        ans = [-1.0] * len(queries)  # --------------------------- step 2.2

		# -------------------------------------------------------- step 2.3
        for i, (qx, qy) in enumerate(queries):
            if qx not in graph or qy not in graph: continue  # 未出现的变量,跳过
            queue = [[qx, 1.0]]     # 初始将起点节点入队
            visited = set()     # 已处理节点
            while queue:
            	# 获取当前处理的节点 node 以及到该节点所得到的权重积mul
                node, mul = queue.pop(0)    
                visited.add(node)
                for neighbor, weight in graph[node].items():  # 枚举该节点的所有邻节点
                    if neighbor == qy:
                        ans[i] = mul * weight   # 找到终点,更新权重积后存储到答案并退出查找
                        break
                    if neighbor not in visited: # 找到一个未处理的邻节点加入队列
                        queue.append([neighbor, mul * weight])  # 将未处理的邻节点及到达该节点时的权重积加入队列
        return ans      

希望对你有帮助呀!!💜💜 如有更好理解的思路,欢迎大家留言补充 ~ 一起加油叭 💦
🔥 LeetCode 热题 HOT 100

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值