399. 除法求值【 力扣(LeetCode) 】
零、LeetCode 原题
一、题目描述
给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi = values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。
另有一些以数组 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 ]
注意:x 是未定义的 => -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 由小写英文字母与数字组成
三、解题思路
3.1 图的路径搜索
- 基本思路:
如果将每个 equations 看作 边 ,value 看作 边权,则 queries 相当于查询某条路径的权重和。 - 具体思路:
- 构建有向图
- 路径搜索
- 如果顶点不存在,则存入 -1 ;
- 如果顶点相同,则存入 1;
- 使用深度搜索进行路径搜索,查找该路径并计算权重累加和。
3.2 路径压缩
- 基本思路:
就在上一个方法的基础上,进行路径压缩即可。每搜索完一个,将结果保存。 - 具体思路:
同上,在最后一步搜索完路径时,保存结果,可以作为下次搜索使用。
四、参考代码
4.1 图的路径搜索
时间复杂度:
O
(
k
∣
E
∣
)
\Omicron(k|E|)
O(k∣E∣)【查找 k 条路径,每条路径最坏情况就是遍历所有的边】
空间复杂度:
O
(
∣
E
∣
)
\Omicron(|E|)
O(∣E∣)【使用空间有:图的边,图的顶点(最坏2倍边的空间),递归深度(最坏遍历所有边),已搜索顶点集合(最坏搜索过所有顶点)】
class Solution {
public:
unordered_map<string, unordered_map<string, double>> m;
double dfs(string now, string obj, unordered_set<string>& used) {
if (m.count(now) == 0)
return 0;
if (m[now].count(obj))
return m[now][obj];
for (const auto& next : m[now]) {
if (used.count(next.first))
continue;
used.emplace(next.first);
auto ans = dfs(next.first, obj, used);
if (ans)
return ans * next.second;
}
return 0;
}
vector<double> calcEquation(vector<vector<string>>& equations,
vector<double>& values,
vector<vector<string>>& queries) {
vector<double> ans;
for (int i = 0; i < equations.size(); i++) {
m[equations[i][0]].emplace(equations[i][1], values[i]);
m[equations[i][1]].emplace(equations[i][0], 1 / values[i]);
}
for (int i = 0; i < queries.size(); i++) {
if (m.count(queries[i][0]) == 0 || m.count(queries[i][1]) == 0) {
ans.emplace_back(-1.0);
} else if (queries[i][0] == queries[i][1]) {
ans.emplace_back(1.0);
} else {
unordered_set<string> used;
ans.emplace_back(dfs(queries[i][0], queries[i][1], used));
if (ans.back() == 0.0)
ans.back() = -1.0;
}
}
return ans;
}
};
4.2 路径压缩
时间复杂度:
O
(
k
α
(
∣
E
∣
)
)
\Omicron(k\alpha(|E|))
O(kα(∣E∣))【
α
(
n
)
\alpha(n)
α(n) 是一个增长很慢的函数,其值都不超过 4】
空间复杂度:
O
(
∣
E
∣
)
\Omicron(|E|)
O(∣E∣)
class Solution {
public:
unordered_map<string, unordered_map<string, double>> m;
double dfs(string now, string obj, unordered_set<string>& used) {
if (m.count(now) == 0)
return 0;
if (m[now].count(obj))
return m[now][obj];
for (const auto& next : m[now]) {
if (used.count(next.first))
continue;
used.emplace(next.first);
auto ans = dfs(next.first, obj, used);
if (ans)
return ans * next.second;
}
return 0;
}
vector<double> calcEquation(vector<vector<string>>& equations,
vector<double>& values,
vector<vector<string>>& queries) {
vector<double> ans;
for (int i = 0; i < equations.size(); i++) {
m[equations[i][0]].emplace(equations[i][1], values[i]);
m[equations[i][1]].emplace(equations[i][0], 1 / values[i]);
}
for (int i = 0; i < queries.size(); i++) {
if (m.count(queries[i][0]) == 0 || m.count(queries[i][1]) == 0) {
ans.emplace_back(-1.0);
} else if (queries[i][0] == queries[i][1]) {
ans.emplace_back(1.0);
} else {
unordered_set<string> used;
ans.emplace_back(dfs(queries[i][0], queries[i][1], used));
if (ans.back() == 0.0)
ans.back() = -1.0;
else{ // 保存结果
m[queries[i][0]].emplace(queries[i][1],ans.back());
m[queries[i][1]].emplace(queries[i][0],1/ans.back());
}
}
}
return ans;
}
};
原文地址:https://blog.csdn.net/yyh520025/article/details/144659052
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!