【leetcode-42】【并查集】399. 除法求值

题目描述

给出方程式 A / B = k, 其中 A 和 B 均为用字符串表示的变量, k 是一个浮点型数字。根据已知方程式求解问题,并返回计算结果。如果结果不存在,则返回 -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 ]

示例 2:
输入:equations = [[“a”,“b”],[“b”,“c”],[“bc”,“cd”]], values = [1.5,2.5,5.0], queries = [[“a”,“c”],[“c”,“b”],[“bc”,“cd”],[“cd”,“bc”]]
输出:[3.75000,0.40000,5.00000,0.20000]

示例 3:
输入:equations = [[“a”,“b”]], values = [0.5], queries = [[“a”,“b”],[“b”,“a”],[“a”,“c”],[“x”,“y”]]
输出:[0.50000,2.00000,-1.00000,-1.00000]

提示:
1 <= equations.length <= 20
equations[i].length == 2
1 <= equations[i][0].length, equations[i][1].length <= 5
values.length == equations.length
0.0 < values[i] <= 20.0
1 <= queries.length <= 20
queries[i].length == 2
1 <= queries[i][0].length, queries[i][1].length <= 5
equations[i][0], equations[i][1], queries[i][0], queries[i][1] 由小写英文字母与数字组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/evaluate-division
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

  • 找一个公共祖先,比如求a / b,实际上是求a / root 除以 b / root,这里我们使用并查集,但不压缩路径。
  • 因为要记录除得得结果,因此还需要有一个map来记录除以root的值,高端点也可以叫做权重。
  • 首先初始化每个数的root是自己,且权重为1。
  • 根据已知条件,将equations中的两个数进行合并,equation[i][0]的根节点如果和equations[i][1]的根节点不相同的话,设equations[i][0]的根节点设为equations[i][0]的根节点的子节点,并更新权重/好绕啊,实际代码如下
    parent.put(p1.getKey(), p2.getKey());
    weight.put(p1.getKey(), val * p2.getValue() / p1.getValue());
    
  • getPair函数中,实现了查找输入节点的root节点并返回权重的功能

代码

class Solution {
    
    
    HashMap<String, String> parent = new HashMap<>();
    HashMap<String, Double> weight = new HashMap<>();
    // Pair<String, Double> String是祖先节点,Double是权重
    public Pair<String, Double> getPair(String node){
    
    
        if(!parent.containsKey(node)){
    
    
            return new Pair<String, Double>("", -1.0);
        }
        double _weight = 1;
        while(parent.get(node) != node){
    
    
        	// a/c = a/b * b/c,所以一直是乘的关系。
            _weight *= weight.get(node);
            node = parent.get(node);
        }
        return new Pair<>(node, _weight);
    }
    private void combine(String a, String b, double val){
    
    
        Pair<String, Double> p1 = getPair(a);
        Pair<String, Double> p2 = getPair(b);
        if(p1.getKey() == "" || p2.getKey() == "" ) return;
        if(p1.getKey() == p2.getKey()) return;
        parent.put(p1.getKey(), p2.getKey());
        weight.put(p1.getKey(), val * p2.getValue() / p1.getValue());
    }
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
    
    
        double[] res = new double[queries.size()];
        int i = 0;
        for(List<String> item : equations){
    
    
            if(getPair(item.get(0)).getKey() == ""){
    
    
                parent.put(item.get(0), item.get(0));
                weight.put(item.get(0), 1.0);
            }
            if(getPair(item.get(1)).getKey() == ""){
    
    
                parent.put(item.get(1), item.get(1));
                weight.put(item.get(1), 1.0);
            }
            combine(item.get(0), item.get(1), values[i++]);
        }
        i = 0;
        for(List<String> item : queries){
    
    
            Pair<String, Double> p1 = getPair(item.get(0));
            Pair<String, Double> p2 = getPair(item.get(1));
            if(!parent.containsKey(p1.getKey()) || !parent.containsKey(p2.getKey()) || p1.getKey() != p2.getKey()){
    
    
                res[i++] = -1.0;
            } else {
    
    
            	// a/b = (a*d*e*f) / (b*d*e*f)
                res[i++] = p1.getValue() / p2.getValue();
            }
        }
        return res;
    }
}

猜你喜欢

转载自blog.csdn.net/u010659877/article/details/109071936
今日推荐