【LeetCode】399. 除法求值 并查集

在这里插入图片描述
在这里插入图片描述

这道题目的解法是带权值的并查集。

并查集

可以看这篇文章的讲解:

https://blog.csdn.net/niushuai666/article/details/6662911

并查集由一个整数型的数组和两个函数构成。数组pre[]记录了每个点的前导点是什么,函数find是查找,join是合并

解题思路:建立两个map,一个map存储上一级结点。一个map存储比值。首先不断构建查并集结构。如果两者根节点不一致,进行合并。然后输出最终的结果即可。

在这里插入图片描述

public class Solution {
    HashMap<String, String> path = new HashMap<>();  // key是当前结点,value是父结点
    HashMap<String, Double> value = new HashMap<>();  // key是当前结点,value是父结点/此结点

    public double[] calcEquation(List<List<String>> equations,
                                 double[] values,
                                 List<List<String>> queries) {
        // 这道题目用并查集的方式来求解。
        // 带权值的并查集。
        for (int i = 0; i < values.length; i++) {// 遍历被除数,除数,商。
            String parent = equations.get(i).get(0);
            String child = equations.get(i).get(1);
            double divide = values[i];
            // 首先保证 map中有这两个结点。
            if (!path.containsKey(parent)) {
                path.put(parent, parent);
                value.put(parent, 1.0);
            }
            if (!path.containsKey(child)) {
                path.put(child, child);
                value.put(child, 1.0);
            }
            String root1 = findRoot(parent);// 找到了parent的根节点
            String root2 = findRoot(child);// 找到了,child的根节点
            // 分成两种情况,两者根节点一致;两者根节点不一致。
            // 一致的话,不用管了。不一致的话,进行根节点的合并。
            if(!root1.equals(root2)){
                path.put(root2,root1);
                value.put(root2,divide*value.get(parent)/value.get(child));
            }
        }
        // 现在已经将数据按照并查集的格式存储好了
        double[] res = new double[queries.size()];
        for (int i = 0; i< queries.size(); i++) {
            List<String> query = queries.get(i);
            String s1 = query.get(0);
            String s2 = query.get(1);
            if(!(path.containsKey(s1)&&path.containsKey(s2))){
                res[i] = -1.0;
                continue;
            }
            // 说明 两者都包括
            String root1 = findRoot(s1);
            String root2 = findRoot(s2);
            if(!root1.equals(root2)){
                res[i] = -1.0;
                continue;
            }
            // 说明 两者的根结点一致。
            res[i] = value.get(s2)/value.get(s1);
        }
        return res;
    }

    private String findRoot(String str) {
        // 这个方法能够找到,str的根结点。
        // 并且最终将此结点直接与根节点相连。(设置其value值)
        String save = str;
        double divide = 1.0;
        if (path.get(str).equals(str)) {
            return str;
        }
        // 说明root不是自己。
        while (!path.get(str).equals(str)) {
            // 如果str的父结点 不等于 str
            divide *= value.get(str);
            str = path.get(str);
        }
        divide *= value.get(str);
        path.put(save, str);
        value.put(save, divide);
        return str;
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值