leetcode399. Evaluate Division

栏目: 编程工具 · 发布时间: 5年前

内容简介:已知一些字母之间的关系式,问是否能够计算出其它字母之间的倍数关系?如已知假如我们将除数和被除数看做是图的顶点,将除数和被除数之间的倍数关系试做二者之间边的权重。即

题目要求

Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.

Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].

The input is: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector<double>.

According to the example above:

equations = [ ["a", "b"], ["b", "c"] ],
values = [2.0, 3.0],
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]. 
 

The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.

已知一些字母之间的关系式,问是否能够计算出其它字母之间的倍数关系?

如已知 a/b=2.0 b/c=3.0 问是否能够计算出 a/c, b/a, a/e, a/a, x/x 的值。如果无法计算得出,则返回-1。这里 x/x 的值因为在条件中无法获知x是否等于零,因此也无法计算其真实结果,也需要返回-1。

思路和代码

假如我们将除数和被除数看做是图的顶点,将除数和被除数之间的倍数关系试做二者之间边的权重。即 a/b=2.0 代表点a指向点b的边的权重为2.0,而点b指向点a的边的全中为1/2.0=0.5。

因此我们可以将输入的表达式转化为一个加权有向图,而题目的问题则被转化为求两个点之间是否能够找到一条边,如果无法找到,则返回-1,否则返回路径上每条边的权重的乘积。

代码如下:

public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        //图的链式表示法
        Map<String, List<String>> pairs = new HashMap<>();
        //图上每条边的权重
        Map<String, List<Double>> valuedPairs = new HashMap<>();
        for(int i = 0 ; i < equations.size() ; i++) {
            //获取第i个方程式
            List<String> equation = equations.get(i);
            String multiplied = equation.get(0);//被除数
            String multiplier = equation.get(1);//除数
            //如果被除数从来没有添加到图中,则将其作为顶点在图中初始化
            if(!pairs.containsKey(multiplied)) {
                pairs.put(multiplied, new ArrayList<>());
                valuedPairs.put(multiplied, new ArrayList<>());
            }
            //如果除数从来没有添加到图中,则将其作为顶点在图中初始化
            if(!pairs.containsKey(multiplier)) {
                pairs.put(multiplier, new ArrayList<>());
                valuedPairs.put(multiplier, new ArrayList<>());
            }
            //添加边和边的权重
            pairs.get(multiplied).add(multiplier);
            pairs.get(multiplier).add(multiplied);
            valuedPairs.get(multiplied).add(values[i]);
            valuedPairs.get(multiplier).add(1.0 / values[i]);
        }
        
        //结果集
        double[] result = new double[queries.size()];
        for(int i = 0 ; i<queries.size() ; i++) {
            //在图中,以被除数作为顶点,深度优先遍历图,直到找到值为除数的顶点
            result[i] = dfs(queries.get(i).get(0), queries.get(i).get(1), pairs, valuedPairs, new HashSet<>(), 1.0);
            result[i] = result[i]==0.0 ? -1.0 : result[i];
        }
        return result;
    }
    
    public double dfs(String multiplied, String multiplier, Map<String, List<String>> pairs, Map<String, List<Double>> valuedPairs, Set<String> visited, double curResult) {
        //如果图中不包含该被除数顶点,则无法获知该表达式的值
        if(!pairs.containsKey(multiplied)) return 0.0;
        //如果再次访问过该被除数,说明找到了一条环路,则该深度优先遍历结果失败,直接抛弃
        if(visited.contains(multiplied)) return 0.0;
        //如果被除数等于除数,则返回1.0
        if(multiplied.equals(multiplier)) return curResult;
        visited.add(multiplied);
        //获得当前被除数的所有邻接顶点
        List<String> multipliers = pairs.get(multiplied);
        //获得所有邻接边的权重
        List<Double> multiplierValues = valuedPairs.get(multiplied);
        double tmp = 0.0;
        for(int i = 0 ; i<multipliers.size() ; i++) {
            //以邻接点为新的顶点,继续深度优先遍历
            //此时调用方法中curResult的值代表的是该原邻接点除以邻接点的值
            //如 a/b=2, b/c=3, 则a=2b,因此当我们以b作为邻接点寻找c时,需要记录原被除数是现被除数的两倍
            tmp = dfs(multipliers.get(i), multiplier, pairs, valuedPairs, visited, curResult * multiplierValues.get(i));
            //找到非零路径,结束深度优先遍历
            if(tmp != 0.0){
                break;
            }
        }
        visited.remove(multiplied);
        return tmp;
    }

以上所述就是小编给大家介绍的《leetcode399. Evaluate Division》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入Linux内核架构

深入Linux内核架构

Wolfgang Mauerer / 郭旭 / 人民邮电出版社 / 201005 / 149.00元

众所周知,Linux操作系统的源代码复杂、文档少,对程序员的要求高,要想看懂这些代码并不是一件容易事。本书结合内核版本2.6.24源代码中最关键的部分,深入讨论Linux内核的概念、结构和实现。具体包括进程管理和调度、虚拟内存、进程间通信、设备驱动程序、虚拟文件系统、网络、时间管理、数据同步等方面的内容。本书引导你阅读内核源代码,熟悉Linux所有的内在工作机理,充分展现Linux系统的魅力。 ......一起来看看 《深入Linux内核架构》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试