【LeetCode】399. 除法求值

题目

399. 除法求值

给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi]values[i] 共同表示等式 Ai / Bi = values[i] 。每个 AiBi 是一个表示单个变量的字符串。

另有一些以数组 queries 表示的问题,其中 queries[j] = [Cj, Dj] 表示第 j 个问题,请你根据已知条件找出 Cj / Dj = ? 的结果作为答案。

返回 所有问题的答案 。如果存在某个无法确定的答案,则用 -1.0 替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用 -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 = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]]
输出:[3.75000,0.40000,5.00000,0.20000]

示例 3:

输入:equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]]
输出:[0.50000,2.00000,-1.00000,-1.00000]

提示:

  • 1 <= equations.length <= 20
  • equations[i].length == 2
  • 1 <= Ai.length, Bi.length <= 5
  • values.length == equations.length
  • 0.0 < values[i] <= 20.0
  • 1 <= queries.length <= 20
  • queries[i].length == 2
  • 1 <= Cj.length, Dj.length <= 5
  • Ai, Bi, Cj, Dj 由小写英文字母与数字组成

思路

  • 除法的传递相当于有向图的传递,若能从根节点遍历到目的节点,则说明可以计算出结果,否则则说明无法计算出结果
  • 因为本体中图可以双向传递,且可能出现环,所以声明一个集合保存遍历过的
  • 正向传递为乘法,反向传递为除法,为简便计算可以将反向传递的值取相反数
  • 使用dfs遍历图,若能遍历到结果则返回,否则返回None,若最后计算结果为None,则返回-1

代码

from typing import List


class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        valueMap = {}
        for i in range(len(values)):
            valueMap[(equations[i][0], equations[i][1])] = values[i]
            valueMap[(equations[i][1], equations[i][0])] = 1/values[i]
        adjGraph = {}
        for a,b in equations:
            if a not in adjGraph: adjGraph[a] = {b}
            else: adjGraph[a].add(b)
            if b not in adjGraph: adjGraph[b] = {a}
            else:
                adjGraph[b].add(a)
        def calc(left: str, right: str):
            visited = set()
            def dfs(root: str, curVal: float):
                if root==right: return curVal
                if not root:
                    return None
                if root in adjGraph:
                    for end in adjGraph[root]:
                        if (root,end) in valueMap and (root, end) not in visited:
                            visited.add((root, end))
                            ret = dfs(end, curVal*valueMap[(root,end)])
                            if ret: return ret    
                return None
            if left in adjGraph:
                for end in adjGraph[left]:
                    if (left,end) in valueMap:
                        visited.add((left,end))
                        ret = dfs(end, valueMap[(left,end)])
                        if ret: return ret
            return -1
        ret = []
        for query in queries:
            ret.append(calc(query[0], query[1]))
        return ret

复杂度

  • M M M为边的数量, Q Q Q为询问的数量, L L L为字符串的平均长度
  • 时间复杂度: O ( M L + Q ( L + M ) ) O(ML+Q(L+M)) O(ML+Q(L+M)), O ( M L ) O(ML) O(ML)为构图复杂度, O ( Q ( L + M ) ) O(Q(L+M)) O(Q(L+M))为单个计算的复杂度
  • 空间复杂度: O ( N L + M ) O(NL+M) O(NL+M) O ( N L ) O(NL) O(NL)为图键的空间复杂度, O ( M ) O(M) O(M)为遍历和图值的复杂度

你可能感兴趣的:(leetcode,深度优先,算法)