带权并查集:Leetcode 399 除法求值

带权并查集:Leetcode 399 除法求值

问题:

在这里插入图片描述

思路:

构建带权值边的并查集,对于每个方程式有两种情况:
查询是否联通,若不联通,则答案为-1.0
若联通,则求出其与根相除的结果,根据结果计算方程式。

例如,对于题目示例:

构造并查集:a->b->c,其中a->b的边的权值为2.0,b->c的边的权值为3.0
以计算b/a时为例,以root结点为桥梁,计算b/a的值:
首先计算b/root,这里root为c,则b/c = 3.0
然后计算a/root,这里root为c,则a/c = (a/b) * (b/c) = 2.0 * 3.0 = 6.0
最后计算方程式结果:b/a = (b/root)/(a/root) = 3.0/6.0 = 0.5

建立map<string,string>保存节点的parent,建立map<string,double> 保存节点除以parent的值
以a/b=2.0 ,b/c=3.0为例:
在这里插入图片描述
find函数用于返回节点的根以及节点除以根的值

union函数在合并的同时需对weight进行更新:

parent[rootA.first]=rootB.first;
weight[rootA.first]=1/rootA.second*a_div_b*rootB.second;

rootA.second由find(a)的返回值得到,即等于a/a的根
a_div_b等于a/b
rootB.second由find(b)的返回值得到,即等于b/b的根
weight[rootA.first]的值应等于 a的根/b的根
即weight[rootA.first]=1/rootA.second * a_div_b * rootB.second
在这里插入图片描述
对每个已知方程式的两个字符串进行union操作

对每个未知方程式的两个字符串进行find操作
若两个字符串的根均存在且相同,则返回两个find函数的商,即(a/root)/(b/root) = a/b即为所求

代码:

class Solution {
public:
    unordered_map< string,string > parent;
    unordered_map< string,double > weight;
    pair< string,double > find( string a )
    {
        if( parent.find( a )==parent.end() )
            return { " ",-1.0 };
        double result=1.0;
        while( parent[a]!=a )
        {
            result*=weight[a];
            a=parent[a];
        }
        return {a,result};      
    }
    void set_union( string a,string b,double a_div_b )
    {
        pair< string,double > rootA=find(a);
        pair< string,double > rootB=find(b);
        if( rootA.first==" " || rootB.first==" " )
            return;
        if( rootA.first==rootB.first )
            return;
        parent[rootA.first]=rootB.first;
        weight[rootA.first]=1/rootA.second*a_div_b*rootB.second;
    }
    vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
        int i;
        for( i=0;i<equations.size();i++ )
        {
            string a=equations[i][0];
            string b=equations[i][1];
            if( parent.find( a )==parent.end() )
            {
                parent[a]=a;
                weight[a]=1;
            }
            if( parent.find(b)==parent.end() )
            {
                parent[b]=b;
                weight[b]=1;
            }
            set_union( a,b,values[i] );
        }
        vector<double> ans;
        for( i=0;i<queries.size();i++ )
        {
            string a=queries[i][0];
            string b=queries[i][1];
            pair<string,double> a_div_root =find(a);
            pair<string,double> b_div_root = find(b);
            if( a_div_root.first==" " || b_div_root.first==" " || a_div_root.first!=b_div_root.first )
                ans.push_back(-1.0);
            else
                ans.push_back( a_div_root.second/b_div_root.second );
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

happy19991001

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值