leetcode399 除法求值 并查集与DFS

**给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi = values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。

另有一些以数组 queries 表示的问题,其中 queries[j] = [Cj, Dj] 表示第 j 个问题,请你根据已知条件找出 Cj / Dj = ? 的结果作为答案。

返回 所有问题的答案 。如果存在某个无法确定的答案,则用 -1.0 替代这个答案。

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/evaluate-division
**

示例
输入: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 ]

class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        graph_dic=collections.defaultdict(dict)  # 防止出现keyError 默认值是dict
        for [divis, divid], value in zip(equations, values):
            graph_dic[divis][divid] = value  # 嵌套字典
            graph_dic[divid][divis] = 1.0/value
        def Dfs(graph_dic, visit, i, j):
            if j in graph_dic[i]: return graph_dic[i][j]  # 证明i能直接到达j 
            # j是间接邻接与i i无法一步到达j 则需要通过D与i邻接的结点找到j
            # 这里不用注意j是否能间接邻接与i 访问到所有i邻接的结点就可以判断j是否能邻接与i
            # 接下来就是要遍历i邻接的结点 再递归调用Dfs 
            for child in graph_dic[i]:
                if child not in visit:  # 结点未被访问到
                    visit.add(child)
                    ret = Dfs(graph_dic, visit, child, j)  # 递归 现在是child到j 而不是i到j
                    if ret != -1:
                        return graph_dic[i][child]*ret  # 乘上i到child的权值
            return -1  # 证明i的child里面 没有一个是邻接与j的
        ans = []
        # 枚举所有路径组合
        for i, j in queries:
            if i not in graph_dic or j not in graph_dic:
                ans.append(-1.0)
            elif i == j:
                ans.append(1.0)
            else:
                ans.append(Dfs(graph_dic, set(), i, j))
        return ans




        # 并查集
        # 首先初始化一个字典 包含所有除数与被除数
        div = {
     }
        for divis, divid in equations:
            div[divis] = [divis, 1]  # 代表初始化时 每个结点父亲都是自己 权值为1
            div[divid] = [divid, 1]
        
        # find 路径压缩 一层一层往上寻找根结点
        def find(i):
            if i != div[i][0]:  # 非根结点
                origin = div[i][0]  # 记录下上一层结点 更新权值
                div[i][0] = find(div[i][0])  # 递归查询上一层结点
                div[i][1] *= div[origin][1]  
                # a --(3.0)> b --(2.0)>c 一层一层往上找 则 a --(rank)>c rank=3.0*2.0
            return div[i][0]
        
        # union 
        def union(i, j, val):
            parentOfi = find(i)
            parentOfj = find(j)
            if parentOfi != parentOfj:
                div[parentOfj][0] = parentOfi
                div[parentOfj][1] = div[i][1]*val/div[j][1]
        

        for [i, j], val in zip(equations, values):
            union(i, j, val)

        ans = []
        for i, j in queries:
            if i not in div or j not in div:
                ans.append(-1.0)
            else:
                if i == j:
                    ans.append(1.0)
                elif find(i) == find(j):
                    ans.append(div[j][1]/div[i][1])
                else:
                    ans.append(-1.0)
        return ans

你可能感兴趣的:(From,Python,dfs,算法)