leetcode-399.除法求值之并查集

这篇博客探讨了一种在LeetCode中遇到的图相关问题,通过并查集算法解决。作者解释了如何将相除关系转化为图的结构,并利用并查集的合并与查找操作来建立和查询变量之间的联通关系。文章以求解变量间换算比例为例,详细阐述了并查集的实现过程,包括路径压缩和权重计算。此外,还用帮派合并的形象比喻帮助理解并查集的工作原理。
摘要由CSDN通过智能技术生成

题目

在这里插入图片描述
这道题要是不知道并查集的方法还可以通过DFS或BFS来做,这也是我第一次在leetcode遇到图相关的题目,很有意义!事实上题中的相除关系可以通过图的方式来表达,而queries中的求商可以通过求换算关系来得到,比如求a/d,那么我们要是能够将a和d都换算成相同的中间变量即可!
我们可将a/b = 2.0变为两个顶点和一个边的关系来表示,a—>b,权重为2; 那么再加上b/c = 3.0,将图扩展为a—>b—>c,权重分别为2.0,3.0。那么当我们要求a/c的值的时候,只需要求a到c的值即可!
那么我们可以应用并查集的方法了:并查集由两步组成,分别是合并union和查找find,合并是将并不联通的两个图通过代表元进行联通,那么联通后的两个图就成为一个图,有同样的代表元了!而查找就是通过一个顶点查找该顶点所在图中的代表元!在本题中合并可以用于建立equations各个变量的联通关系(除法关系),在同一联通图的变量(顶点)可以换算成同一另一元素(代表元),查找用于找一个变量可以换算到另外一个变量(代表元),同时添加方法计算从被查找顶点到代表元的权值乘积!
在一个讲解并查集的博客中看到一个很有意思的理解方式,我们可以将合并操作理解为帮派的合并,而代表元就是一个帮派的老大,那么帮派的合并自然要是A帮的帮主投靠B帮的B帮主或是B帮的B帮主A帮的帮主了!而查找操作可以理解为底下的小弟去找老大!并查集还有Rank优化,路径压缩等优化操作,在此不累书。

class Solution {
public:
    unordered_map<string, string> parents;
    unordered_map<string, double> weights;
    
    // 查找
    string Find(string s, double& results){
        string s_root = s;
        while(parents.count(s_root)>0){
            results*=weights[s_root];
            s_root = parents[s_root];
        }
        return s_root;   
    }

    //合并
    void Union(string x, string y, double x_y){
        double x_results = 1;
        double y_results = 1;
        string x_root = Find(x,x_results);
        string y_root = Find(y,y_results);
        if(x_root == y_root)
            return;
        parents[x_root] = y_root;
        if(weights.count(y) == 0)
            weights[y] = 1.0;
        if(weights.count(x) == 0)
            weights[x] = 1.0;
        if(weights.count(y_root) == 0)
            weights[y_root] = 1.0;
        weights[x_root] = x_y*y_results/x_results;
    }

    vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
        for(int i=0;i<equations.size();i++){
            string x = equations[i][0];
            string y = equations[i][1];
            double x_y = values[i];
            Union(x,y,x_y);
        }
        vector<double> res;
        for(int i=0;i<queries.size();i++){
            string x = queries[i][0];
            string y = queries[i][1];
            double x_result = 1;
            double y_result = 1;
            string x_root = Find(x,x_result);
            string y_root = Find(y,y_result);
            if(weights.count(x) == 0 || weights.count(y)==0)
                res.push_back(-1.0);
            else if(x_root == y_root)
                res.push_back(x_result/y_result);
            else
                res.push_back(-1.0);
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值