Skip to main content

399. Evaluate Division

标签: graph, union-find, depth-first-search

难度: Medium

通过率: 62.49%

原题链接: https://leetcode.com/problems/evaluate-division/description/

题目描述

你被给定了一个由变量对构成的方程数组和一个实数值数组。每个方程的形式为 [Ai,Bi][A_i, B_i],其值为 Ai/Bi=values[i]A_i / B_i = values[i]。每个 AiA_iBiB_i 是表示单个变量的字符串。还给定一些查询,查询为 [Cj,Dj][C_j, D_j],要求你找到 Cj/Dj=?C_j / D_j = ? 的答案。返回所有查询的答案。如果一个答案无法确定,则返回 -1.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 ] 注意: x 是未定义的变量 => -1.0

解题思路

我们可以将每个等式视作图中的一条带权边,其中变量是节点,边的权值是变量之间的比例关系。给定查询等价于在图中寻找两节点之间的路径,并通过路径上的权重计算出结果。可以用深度优先搜索(DFS)或并查集(类似)来实现这个操作。以下是使用DFS方法的解题思路:

  1. 建立有向图:以每个变量为图中的一个节点,用每个比例 (value) 为边的权重,建立有向图的数据结构。例如"a/b=2.0" 可以表示为有向边a -> b,权重为2.0。还需要加上边b -> a,权重为1/2.0,确保图可以双向搜索。
  2. DFS查找路径:对于每个查询,使用DFS在图中搜索从初始节点到目标节点的路径。在搜索过程中累积边权重以得到最终结果。
  3. 处理特殊情况
    • 如果在搜索过程中发现查询涉及未定义的变量,则直接返回 -1。
    • 自身除法返回1(如a/a)。

通过DFS,我们可以有效地查找到任意两点之间的路径,并计算出对应的除法值。

代码实现

def calcEquation(equations, values, queries):
from collections import defaultdict

# 构建图
graph = defaultdict(dict)
for (dividend, divisor), value in zip(equations, values):
graph[dividend][divisor] = value
graph[divisor][dividend] = 1 / value

def dfs(start, end, visited):
# 如果节点已经访问过,跳过(避免循环)
if start not in graph or end not in graph:
return -1.0
if end in graph[start]:
return graph[start][end]
visited.add(start)
for neighbor, value in graph[start].items():
if neighbor not in visited:
temp = dfs(neighbor, end, visited)
if temp == -1:
continue
else:
return value * temp
return -1.0

results = []
for dividend, divisor in queries:
if dividend == divisor:
# 自身除法返回1
if dividend in graph:
results.append(1.0)
else:
results.append(-1.0)
else:
results.append(dfs(dividend, divisor, set()))
return results

复杂度分析

时间复杂度为 O(V×E)O(V \times E),其中 VV 是节点的数量,即不同的变量数量,而 EE 是方程的数量。虽然看起来是二次方,但由于方程数量比较小,有效搜索空间也是有限的。

空间复杂度为 O(V+E)O(V+E),我们需要存储每个变量及其查找到的父节点和权重。