leetcode399 除法求值 并查集与DFS Java与Python AC代码

**给你一个变量对数组 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

Java
DFS

class Solution {
    HashMap<String, HashMap<String, Double>> graph;
    public double dfs(String i, String j, HashSet visit){
        if (graph.get(i).containsKey(j)) return graph.get(i).get(j);
        visit.add(i);
        for (String child : graph.get(i).keySet()){
            if (!visit.contains(child)){
                visit.add(child);
                double rev = dfs(child, j, visit);
                if (rev != -1){
                    rev *= graph.get(i).get(child);
                    return rev;
                }
            }
        }
        return -1.0;
    }
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        graph = new HashMap<>();
        int size = values.length;
        for (int i = 0; i < size; i++){
            graph.put(equations.get(i).get(0), new HashMap<>());
            graph.put(equations.get(i).get(1), new HashMap<>());
        }
        for (int i = 0; i < size; i++){
            graph.get(equations.get(i).get(0)).put(equations.get(i).get(1), values[i]);
            graph.get(equations.get(i).get(1)).put(equations.get(i).get(0), 1/values[i]); 
        }
        double[] ans = new double[queries.size()];
        for (int k = 0; k < queries.size(); k++){
            String i = queries.get(k).get(0);
            String j = queries.get(k).get(1);
            if (!graph.containsKey(i) || !graph.containsKey(j)){
                ans[k] = -1.0;
            }
            else{
                if (i.equals(j)) ans[k] = 1.0;
                else{
                    ans[k] = dfs(i, j, new HashSet<>());
                }
            }
        }

        return ans;
    }
}

并查集

class Solution {
    class Node{
        String parent;
        double weight;
        public Node(String i, double j){
            this.parent = i;
            this.weight = j;
        }
    }
    class UnionFind{
        HashMap<String, Node> f;
        public UnionFind(List<List<String>> equations){
            f = new HashMap<>();
            for (int i = 0; i < equations.size(); i++){
                String u = equations.get(i).get(0), v = equations.get(i).get(1);
                f.put(u, new Node(u, 1.0));
                f.put(v, new Node(v, 1.0));
            }
        }
        public String find(String x){
            if (x != f.get(x).parent){
                String origian = f.get(x).parent;  // 记录下x的上一层节点
                f.get(x).parent = find(f.get(x).parent);
                f.get(x).weight *= f.get(origian).weight;
            }
            return f.get(x).parent;  // 一定要return f.get(x).parent;
        }
        public void union(String i, String j, double val){
            String ri = find(i), rj = find(j);
            if (!ri.equals(rj)){
                f.get(rj).parent = ri;
                f.get(rj).weight = val*f.get(i).weight/f.get(j).weight;
            }
        }
        public boolean isConnect(String i, String j){
            return find(i).equals(find(j));
        }
    }
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        int size = values.length;
        UnionFind un = new UnionFind(equations);
        double[] ans = new double[queries.size()];
        for (int i = 0; i < size; i++){
            un.union(equations.get(i).get(0), equations.get(i).get(1), values[i]);
        }
        for (int i = 0; i < queries.size(); i++){
            String u = queries.get(i).get(0), v = queries.get(i).get(1);
            if (!un.f.containsKey(u) || !un.f.containsKey(v)){
                ans[i] = -1.0;
            }
            else{
                if (u.equals(v)) ans[i] = 1.0;
                else if (un.isConnect(u, v)) ans[i] = un.f.get(v).weight / un.f.get(u).weight;
                else ans[i] = -1.0;
            }
        }
        return ans;
    }
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值