美文网首页
399. 除法求值(Python)

399. 除法求值(Python)

作者: 玖月晴 | 来源:发表于2020-09-17 10:08 被阅读0次

题目

难度:★★★★☆
类型:图
方法:深度优先搜索

力扣链接请移步本题传送门
更多力扣中等题的解决方案请移步力扣中等题目录

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

示例 :

给定 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 ]

输入为: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries(方程式,方程式结果,问题方程式), 其中 equations.size() == values.size(),即方程式的长度与方程式结果长度相等(程式与结果一一对应),并且结果值均为正数。以上为方程式的描述。 返回vector<double>类型。

基于上述例子,输入如下:

equations(方程式) = [ ["a", "b"], ["b", "c"] ],
values(方程式结果) = [2.0, 3.0],
queries(问题方程式) = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
输入总是有效的。你可以假设除法运算中不会出现除数为0的情况,且不存在任何矛盾的结果。

解答

从题目中的要求,是需要求变量与变量之间的关系,而给出的已知信息是变量与大量中间变量之间的关系,因此本题适合用图这种数据结构来做。

图的构建。为了便于表示,这里使用字典来构建图。构建图需要两个主要的信息,即节点与节点之间的关系,函数的输入“equations”就是节点,“values”就是节点之间的关系。为了便于搜索,我们把图构建成双向的,也就是节点与节点之前可以双向到达,对于每一个样本组,即(节点1,节点2,连接权重),可以使用嵌套字典{节点1:{节点2:连接权重}}和{节点2:{节点1:连接权重的倒数}}进行表达。

图的深度优先搜索。本题的要求实际上是求取从源节点到目标节点的路径,并沿着该方向将路径上的所有权重相乘,如果找不到该路径,返回-1。深度优先搜索很适合这类工作,但要注意通过剪枝来控制搜索范围,并且构建足迹集合来避免重复搜索。实现上,首先判断特殊情况,如果源节点或目标节点不在图中,直接返回-1,如果源节点就是目标节点,返回1,其他情况,遍历源节点的相邻节点,如果相邻节点中出现目标节点,说明找到路径,返回连接权重,否则,遍历没有出现在足迹集合的所有相邻节点,通过递归调用探索有没有相邻节点与目标节点之间存在连接。这里注意足迹集合的及时更新,以及最终情况的处理。

class Graph:
    def __init__(self, node_pairs, relations):
        """
        图的初始化,用于构建图中节点与节点中的连接
        :param node_pairs: 图的节点对
        :param relations: 图的节点对之前的关系(权重)
        """
        self.value = dict()
        self.visited = set()    # 用于遍历过程
        for (node1, node2), relationship in zip(node_pairs, relations):
            self.add_node_pair(node1, node2, relationship)

    def refresh(self):
        """
        每次搜寻,需要更新一下
        :return:
        """
        self.visited = set()

    def add_node_pair(self, node1, node2, weight):
        """
        将两个相邻的节点注册在图中,注意节点与节点之间是双向的。
        :param node1: 第一个节点
        :param node2: 第二个节点
        :param weight: 两个节点的关系
        :return:
        """
        def register_nodes(n1, n2, w):
            if n1 in self.value:
                self.value[n1][n2] = w
            else:
                self.value[n1] = {n2: w}

        register_nodes(node1, node2, weight)        # 从节点1到节点2的关系
        register_nodes(node2, node1, 1 / weight)    # 从节点2到节点1的关系

    def search_path(self, source, target):
        """
        寻找从源节点到目标节点的路径
        :param source: 源节点
        :param target: 目标节点
        :return: 如果找到,返回该路径上所有权重的乘积,如果找不到一条路径,返回-1
        """
        if source not in self.value or target not in self.value:        # 如果源节点或者目标节点不在图中,直接返回-1
            return -1
        if source == target:                                            # 如果源节点就是目标节点,返回1
            return 1
        for node in self.value[source].keys():                          # 搜索与当前节点相邻的所有节点
            source2node = self.value[source][node]                      # 获取相邻关系
            if node == target:                                          # 如果相邻节点就是目标节点,说明找到
                return source2node                                      # 返回与源节点的关系
            if node not in self.visited:                                # 如果相邻节点还没有在程序运行过程中遍历过
                self.visited.add(node)                                  # 添加该节点到历史记录
                result = self.search_path(source=node, target=target)   # 通过深度优先搜索,寻找这个相邻节点与目标节点之前的关系
                if result != -1:                                        # 如果成功找到
                    return source2node * result                         # 建立连接
        return -1                                                       # 如果没有找到它们之前的关系,返回-1


class Solution:
    def calcEquation(self, equations, values, queries):
        graph = Graph(node_pairs=equations, relations=values)
        res = []
        for s, t in queries:
            graph.refresh()
            res.append(graph.search_path(s, t))
        return res


if __name__ == "__main__":
    s = Solution()
    print(s.calcEquation([ ["a", "b"], ["b", "c"] ], [2.0, 3.0], [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]))

如有疑问或建议,欢迎评论区留言~

有关更多力扣中等题的python解决方案,请移步力扣中等题解析

相关文章

  • 399. 除法求值(Python)

    题目 难度:★★★★☆类型:图方法:深度优先搜索 力扣链接请移步本题传送门更多力扣中等题的解决方案请移步力扣中等题...

  • 399. 除法求值

    解法 并查集的思想,将数组转化为图中的权重边,并进行缩短路径,每个都指向根节点

  • Python学习笔记(二)几种除法的比较

    传统除法(' /')、真除法、floor除法(' // ') ·传统除法和真除法:在Python2.7之前,对整数...

  • LeetCode399. 除法求值

    给出方程式 A / B = k, 其中 A 和 B 均为代表字符串的变量, k 是一个浮点型数字。根据已知方程式求...

  • LC399-除法求值

    题目 题目分析 用到的数据结构:map,map的取值,求值。1、遍历得到所有的字母,然后映射成数字。2、将数字组建...

  • 《每周一道算法题》(一)逆波兰表达式求值

    一 逆波兰表达式求值 150. 逆波兰表达式求值 说明: 整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换...

  • iOS算法题(一)逆波兰表达式求值

    一 逆波兰表达式求值 150. 逆波兰表达式求值 说明: 整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换...

  • python 2.7 和 python 3.6 区别(持续更新)

    版本 Python 2.7.14 和 Python 3.6.4 关于除法

  • 2018-10-16

    python学习笔记 标签:用廖雪峰老师的python文档学习,顺手记一点 两种除法 (1)一种除法是/: /除法...

  • 今天一些问题

    1. python 除法 Python 3.x在整数除法中,除法(/)总是返回一个浮点数,如果只想得到整数的结果,...

网友评论

      本文标题:399. 除法求值(Python)

      本文链接:https://www.haomeiwen.com/subject/bhlhyktx.html