算法-Evaluate Division-除法求值

该博客介绍了如何解决LeetCode的除法求值问题,通过构建图结构并利用Floyd算法求解任意两点间的除法结果。文章详细阐述了题目描述、分析、代码实现及复杂度分析,重点在于利用图和Floyd算法来处理相除关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、题目描述

给你一个变量对数组 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 的情况,且不存在任何矛盾的结果。
 

示例 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的每个子集的两个元素之间存在关系,相除的结果在数组values的对应位置中,比如equations.get(0).get(0) / equations.get(0).get(1) = a / b = 2.0。之后求queries的每个子集的计算结果,比如

    a / c = (a / b ) * (b / c)。

  • 什么数据结构能很好的传达这种关系呢?图结构,每条有向边的权重就是相除的结果,寻找两个点相处的结果就是两个点路径的权重和。

  • 怎么表示图呢?用一个二维数组记录两个点之间的权重,没有联系的两个点之间的权重值为-1.0

  • 借助于前提条件和Floyd算法能求出任意两个点之间的距离(权重积)

3、代码实现

class Solution {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        Map<String,Integer> map1 = new HashMap<>();//记录每个节点为键对应的唯一值
        int point_count = 0;//记录已知条件中出现的点的个数
        for(int i = 0;i < equations.size();i++){
            if(!map1.containsKey(equations.get(i).get(0)))
                map1.put(equations.get(i).get(0),point_count++);
             if(!map1.containsKey(equations.get(i).get(1)))
                map1.put(equations.get(i).get(1),point_count++);          
        }
        double[][] graph = new double[point_count][point_count];//记录点之间的权重
        for(int i = 0;i < point_count;i++){//图初始化
            for(int j = 0;j < point_count;j++){
                graph[i][j] = -1.0;
            }
        }
        for(int i = 0;i < equations.size();i++){//已知条件给图赋值
            int va = map1.get(equations.get(i).get(0)),vb = map1.get(equations.get(i).get(1));
            graph[va][vb] = values[i];
            graph[vb][va] = 1.0 / values[i];
        }
        for(int k = 0;k < point_count;k++){//Floyd算法
            for(int i = 0;i < point_count;i++){
                for(int j = 0;j < point_count;j++){
                    if(graph[i][k]  > 0 && graph[k][j] > 0){
                        graph[i][j] = graph[i][k] * graph[k][j];
                    }
                }
            }
        }
        double[] res = new double[queries.size()];//保存结果
        for(int i = 0;i < queries.size();i++){
            List<String> list = queries.get(i);
            double cur = -1.0;//没有联系的点之间-1.0
            if(map1.containsKey(list.get(0)) && map1.containsKey(list.get(1))){
                int va = map1.get(list.get(0)),vb = map1.get(list.get(1));
                if(graph[va][vb] > 0) cur = graph[va][vb];//有联系就更新结果
            }
            res[i] = cur;//赋值
        }
        return res;//返回结果
    }
}

4、复杂度分析

  • 时间复杂度:O(ML+N^3+QL)。构建图需要 O(ML)的时间;Floyd 算法需要 O(N^3)的时间;处理查询时,单次查询只需要 O(L)的字符串比较以及常数时间的额外操作。
  • 空间复杂度:O(NL+N^2)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值