hot100——图

399.除法求值

解题思路

本题已知一个变量对数组,一个实数值数组,其中变量对数组表示等式左边,而实数值数组表示等式右边的结果;而数组queries则表示等式左边,需要我们根据上述已知的变量对数组以及实数值数组得到这个等式右边的结果。如果不存在就返回-1。

本题我们需要用图来做,建立被除数,除数,商的有向图。我们使用邻接表来实现,unordered_map<string, vector<pair<string, double>>> graph;

从题目中可以看到被除数和除数都是以字符串的形式进行存储的,所以这里我们给他们的类型就是string。

a / b = 2.0 <=========> graph["a"] = {"b", 2.0}

那么我们就需要根据题目中给出的equations和values进行建图,

建图具体做法如下:

遍历i个等式,取出第i个等式的被除数和除数,取出相应的value值,存入graph,同时反向的也存储一下,就是b / a = 0.5;

递归遍历:

对于题目中的queries,我们需要从上面建好的图中去递归遍历。取queries中的第j个问题的2个数分别为start和end。

终止条件:

当start==end时,说明在图中找到了这条链路,返回这条链路的乘积即可;

递归:用unordered_set来存储访问过的start数,记作visited,取对应的图graph中相邻的除数中是否存在于visited中,若存在,则说明这条路已经走过,继续往下走;若不存在,则递归遍历除数的邻居,观察是否有链路达到end。

如果返回的乘积不为-1.0,则说明我们找到了当前值的下一个节点之间的链路,返回相应的值,继续递归。

如果遍历所有结果都没有结果,说明graph中不存在start到end的链路,则直接返回-1.0。

查询遍历:

先查看queries中的字符是否存在于graph中,不存在返回-1.0,如果存在被除数和除数相同则返回1.0,其余的用递归来处理结果,初始传入product=1.0,这样不会影响之后的路径权重的乘积。

代码

python

python 复制代码
class Solution(object):
    def calcEquation(self, equations, values, queries):
        """
        :type equations: List[List[str]]
        :type values: List[float]
        :type queries: List[List[str]]
        :rtype: List[float]
        """
        graph = defaultdict(list)
        # 1.建图
        for (a, b), val in zip(equations, values):
            graph[a].append((b, val))
            graph[b].append((a, 1.0/val))
        
        # 查询
        def dfs(start, end, visited, product):
            # 终止条件
            if start == end:
                return product
            visited.add(start)
            for neighbor,weight in graph[start]:
                if neighbor not in visited:
                    ans = dfs(neighbor, end, visited, product * weight)
                    # 只要找到一个有效路径就立即返回,否则继续尝试
                    if ans != -1.0:
                        return ans
            # 说明不存在start到end的路径
            return -1.0


        res = []
        # 判断是否在图中
        for a,b in queries:
            if a not in graph or b not in graph:
                res.append(-1.0)
                continue
            if a==b:
                res.append(1.0)
                continue
            visited= set()
            # 递归查询
            ans = dfs(a, b, visited, 1.0)
            res.append(ans)
        return res

C++

cpp 复制代码
class Solution { 
public:
    // 邻接表,存储graph graph[u] -> (v, weight) 表示 u / v = weight
    unordered_map<string, vector<pair<string, double>>> graph;
    double dfs(string start, string end, unordered_set<string> &visited, double product) 
    {
        // 终止条件 当start==end的时候,返回整条链路的乘积
        if(start==end)
            return product;
        visited.insert(start);
        // 取出graph中对应的除数
        for(auto &p : graph[start])
        {
            string next = p.first;
            double val = p.second;
            // 如果visited中没有next,那么find()迭代器就会返回visited.end()
            // 说明next没有访问过,继续递归
            if(visited.find(next)==visited.end())
            {
                double res = dfs(next, end, visited, product * val);
                // 一旦res=-1.0,说明这个邻居不行,换下一个邻居继续判断
                // 不等于-1.0,返回当前邻居结果,继续下一层遍历
                if(res!=-1.0)
                    return res;
            }
                
            // 说明next存在visited中,继续递归
        }
        // 遍历所有结果都没有,说明graph中不存在从start到end的链路,返回-1.0
        return -1.0;

    }

    vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
        // 1. 建图
        for(int i=0;i<equations.size();i++)
        {
            // 取出被除数和除数
            string a = equations[i][0];
            string b = equations[i][1];   
            // 取出相应的商
            double val = values[i];
            // 存入图中
            graph[a].push_back({b, val});
            graph[b].push_back({a, 1/val});     
        }

        // 2. 递归得到乘积结果
        vector<double> res;
        for(int j=0;j<queries.size();j++)
        {
            string start = queries[j][0];
            string end = queries[j][1];
            // 被除数和除数二者之一不存在graph中,直接返回-1.0
            if(graph.find(start)==graph.end() || graph.find(end)==graph.end())
            {
                res.push_back(-1.0);
                continue;
            }
            // 被除数和除数相同,则直接返回1.0
            if(start==end)
            {
                res.push_back(1.0);
                continue;
            }
            // 进入递归处理结果
            unordered_set<string> visited;
            double ans = dfs(start, end, visited, 1.0);
            res.push_back(ans);
            
        }
        return res;
    }
};
相关推荐
数据皮皮侠7 分钟前
上市公司内源与债权股权融资协同数据(2009-2025)
大数据·人工智能·算法·microsoft·百度
KillerNoBlood10 分钟前
2026移动端跨平台开发面经总结
android·算法·flutter·ios·移动开发·鸿蒙·kmp
basketball61612 分钟前
C++ Lambda 表达式完全指南
开发语言·c++·算法
不知名的老吴13 分钟前
C++中emplace函数的不适场景总结(三)
开发语言·c++·算法
玉树临风ives35 分钟前
atcoder ABC 457 题解
数据结构·c++·算法
驭渊的小故事44 分钟前
Java数据结构集合框架(栈(Stack)的详细解析)2000字详细解析
数据结构
宵时待雨1 小时前
回溯算法专题1:递归
数据结构·c++·笔记·算法·leetcode·深度优先
爱思德学术1 小时前
【SPIE出版】黄冈师范学院主办!第四届大数据、计算智能与应用国际会议(BDCIA 2026)
大数据·算法·数据分析·云计算·etl
洛水水1 小时前
【力扣100题】40.二叉树中的最大路径和
算法·leetcode·深度优先
洛水水1 小时前
【力扣100题】37.从前序与中序遍历序列构造二叉树
c++·算法·leetcode