day62(1.21)——leetcode面试经典150

399. 除法求值

399. 除法求值

我真服了江西这个天气,气死我了,这么冷 想冻死谁 我搁着敲代码手都要冻僵了 气死了 想回学校了 这么冷 谁写的动 真要要被冻死了啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

题目:

题解:

java 复制代码
class UnionFind {
    private final int[] fa; // 代表元
    public final double[] mul; // x 的值 * mul[x] = x 的代表元的值

    public UnionFind(int n) {
        fa = new int[n];
        // 一开始有 n 个集合 {0}, {1}, ..., {n-1}
        // 集合 i 的代表元是自己,自己 * 1 = 自己
        for (int i = 0; i < n; i++) {
            fa[i] = i;
        }

        mul = new double[n];
        Arrays.fill(mul, 1);
    }

    // 返回 x 所在集合的代表元
    // 同时做路径压缩,也就是把 x 所在集合中的所有元素的 fa 都改成代表元
    private int find(int x) {
        if (fa[x] != x) {
            int root = find(fa[x]);
            mul[x] *= mul[fa[x]]; // 更新 x 到其代表元的 mul 值
            fa[x] = root;
        }
        return fa[x];
    }

    // 判断 x 和 y 是否在同一个集合
    public boolean same(int x, int y) {
        // 如果 x 的代表元和 y 的代表元相同,那么 x 和 y 就在同一个集合
        // 这就是代表元的作用:用来快速判断两个元素是否在同一个集合
        return find(x) == find(y);
    }

    // 合并 from 和 to,新增信息 to / from = value
    // 其中 to 和 from 表示未知量,下文的 x 和 y 也表示未知量
    public void merge(int from, int to, double value) {
        int x = find(from);
        int y = find(to);
        if (x == y) { // from 和 to 在同一个集合,不做合并
            return;
        }
        //    x --------- y
        //   /           /
        // from ------- to
        // 已知 x/from = mul[from] 和 y/to = mul[to],现在合并 from 和 to,新增信息 to/from = value
        // 由于 y/from = (y/x) * (x/from) = (y/to) * (to/from)
        // 所以 y/x = (y/to) * (to/from) / (x/from) = mul[to] * value / mul[from]
        mul[x] = mul[to] * value / mul[from];
        fa[x] = y;
    }
}

class Solution {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        // 把不同字符串映射为不同的数字,方便使用并查集
        Map<String, Integer> variableToId = new HashMap<>();
        for (List<String> equation : equations) {
            for (String s : equation) {
                variableToId.putIfAbsent(s, variableToId.size());
            }
        }

        // 初始化并查集
        UnionFind uf = new UnionFind(variableToId.size());
        for (int i = 0; i < equations.size(); i++) {
            List<String> equation = equations.get(i);
            uf.merge(variableToId.get(equation.get(1)), variableToId.get(equation.get(0)), values[i]);
        }

        // 回答询问
        double[] ans = new double[queries.size()];
        for (int i = 0; i < queries.size(); i++) {
            List<String> query = queries.get(i);
            Integer c = variableToId.get(query.get(0));
            Integer d = variableToId.get(query.get(1));
            if (c != null && d != null && uf.same(c, d)) {
                //    c * mul[c] = d * mul[d] = 代表元的值
                // => c / d = mul[d] / mul[c]
                ans[i] = uf.mul[d] / uf.mul[c];
            } else {
                ans[i] = -1;
            }
        }
        return ans;
    }
}
相关推荐
晨米酱2 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
彧azz2 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试
CoderYanger2 天前
A.每日一题:835. 图像重叠
java·开发语言·程序人生·leetcode·面试·职场和发展·学习方法
爱学习的执念2 天前
助力金九银十1000道软件测试面试题(功能、接口、自动化、WEB、APP.......)附答案
软件测试·面试
小的~~2 天前
银河麒麟V10 ARM部署TDengine(涛思)工业时序数据库安装与测试
面试·程序员创富
2401_832298102 天前
人机协同:AI时代全新工作与学习范式
职场和发展
童园管理札记2 天前
从政策驱动到课堂落地:2026年“人工智能+教育”全景解读与技术实践指南
人工智能·python·深度学习·职场和发展·学习方法
小刘在重生~2 天前
Oracle_day2 单行函数|组函数|分组|伪列|子查询|分页|多表连接
笔记·oracle·面试
Sam_Deep_Thinking2 天前
关于java final关键字的可见性
java·后端·面试·程序员
yuanxi2002 天前
卡塔尔能源公司LNG扩建项目首条生产线预计明年投运:大客户销售的5个判断
职场和发展·创业创新·学习方法