心路历程:
一开始看着挺蒙的主要是不知道这道题在考察哪个知识点,后来按顺序把三个示例自己模拟着做出来之后发现本质其实在考类似链表或者指针的东西。
再一想其实是一个树或者图的遍历搜索问题,一下子想到了回溯算法。
第一次遇到这个题从读题到最后AC一共用了17分钟。当时犹豫了很久除法溢出的问题,后来想想就算有溢出问题也可以用path存储一个路径再去乘法。但是其实这道题给float留的裕度很大,直接用path /= number也可以直接AC。
做完之后看网上的答案基本上也是按照图+DFS的思路来做的
注意的点:
1、注意回溯函数nonlocal的声明,因为有些变量不是List Objective
2、注意每次初始化回溯的几大参数(path, res, visited, flag)
3、初始化visited = [start]而不是[],由于回溯函数的循环不变量编程原则。
解法: 建图(树)+DFS
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
# 1. 建双向树 (其实是个图)
element = {}
for i in range(len(equations)):
(x, y) = equations[i]
if x not in element: element[x] = [(y, values[i])]
else: element[x].append((y, values[i]))
if y not in element: element[y] = [(x, 1.0 / values[i])]
else: element[y].append((x, 1.0 / values[i]))
# 2. 树的回溯函数
def dfs(start, target):
nonlocal path, visited, flag, res # 2
if start == target:
flag = True
res = path # 3
return
candicate = element[start]
for each in candicate:
if each[0] not in visited: # 这是一个能返回的树,所以必须用visited
visited.append(each[0])
path *= each[1]
dfs(each[0], target)
path /= each[1] # ? 这道题没出现溢出问题
visited.pop()
# 3. 回答问题
ans = []
for query in queries:
(x, y) = query # 解包
if x not in element or y not in element: ans.append(-1) # 根本没有这个元素
else: # 注意初始化参数
path, visited, flag, res = 1.0, [x], False, None # 注意visited = [x] 循环不变量
dfs(x, y)
if flag: ans.append(res)
else: ans.append(-1)
return ans