自学内容网 自学内容网

399. 除法求值【 力扣(LeetCode) 】

零、LeetCode 原题


399. 除法求值

一、题目描述

给你一个变量对数组 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 图的路径搜索

  1. 基本思路:
      如果将每个 equations 看作 边 ,value 看作 边权,则 queries 相当于查询某条路径的权重和。
  2. 具体思路:
    • 构建有向图
    • 路径搜索
      • 如果顶点不存在,则存入 -1 ;
      • 如果顶点相同,则存入 1;
      • 使用深度搜索进行路径搜索,查找该路径并计算权重累加和。

3.2 路径压缩

  1. 基本思路:
      就在上一个方法的基础上,进行路径压缩即可。每搜索完一个,将结果保存。
  2. 具体思路:
      同上,在最后一步搜索完路径时,保存结果,可以作为下次搜索使用。

四、参考代码

4.1 图的路径搜索

时间复杂度: O ( k ∣ E ∣ ) \Omicron(k|E|) O(kE)【查找 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)!