399. 除法求值/C++

在这里插入图片描述
并查集
union_nodes函数中ratio的推导
n 1 n_1 n1 n 2 n_2 n2是不同树上的两个节点的值,合并后修改 n 1 n_1 n1 n 1 ′ n'_1 n1,使得比值 n 1 ′ / n 2 = n u m n'_1/n_2=num n1/n2=num,即 n 1 ′ = n u m × n 2 n'_1=num \times n_2 n1=num×n2
r a t i o = n 1 ′ / n 1 = n u m × n 2 / n 1 ratio=n'_1/n_1=num \times n_2/n_1 ratio=n1/n1=num×n2/n1

class Solution {
	//每个节点(除根节点外)都有一个父节点
	//因此整个问题的数据结构就是由多棵树(不是二叉树)组成的森林
    struct Node{
        double val;
        Node* parent;
        Node():parent(nullptr){}
        Node(double value):val(value),parent(nullptr){}
    };
    
    //找到node节点的根节点
    Node* find_parent(Node* node){
        while(node->parent)
            node = node->parent;
        return node;
    }
    
    //将n1与n2所在的树合并为一棵树
    //将n2所在树的根节点p2指定为n1所在树的根节点p1的父节点
    void union_nodes(Node* n1, Node* n2, double num, const unordered_map<string,Node*> &hash){
        Node *p1 = find_parent(n1), *p2 = find_parent(n2);
        double ratio = n2->val * num / n1->val;//此处为n1所在树的所有节点都要乘的系数
        for(auto node : hash)
            if(find_parent(node.second) == p1)
                node.second->val *= ratio;
        p1->parent = p2;
    }
public:
    vector<double> calcEquation(vector<vector<string>>& equations, 
    							vector<double>& values, vector<vector<string>>& queries) {
        unordered_map<string,Node*> hash;//存放已经存在的节点
        vector<double> res;
        
        //建立森林
        for(int i=0;i<equations.size();++i){
            string str1 = equations[i][0];//第一个节点
            string str2 = equations[i][1];//第二个节点
            double value = values[i];//比值node1/node2=value,即node1= node2 * value;
            //当2个节点都不存在时
            if(hash.find(str1) == hash.end() && hash.find(str2) == hash.end()){
            	//由于都不存在,索性将第一个节点的值设为value,第二个节点设为1,这样两者的比值也符合设定
                hash[str1] = new Node(value);
                hash[str2] = new Node(1);
                hash[str2]->parent = hash[str1];
            //只有第一个节点存在
            }else if(hash.find(str1) == hash.end()){
            	//node1 = node2 * value;
                hash[str1] = new Node(hash[str2]->val*value);
                hash[str1]->parent = hash[str2];
            //只有第二个节点存在
            }else if(hash.find(str2) == hash.end()){
            	//node1 = node2 * value,即node2 = node1 / value;
                hash[str2] = new Node(hash[str1]->val/value);
                hash[str2]->parent = hash[str1];
            //两个节点都存在
            }else{
            	//两个节点都存在,则合并两棵树
                union_nodes(hash[str1],hash[str2],value,hash);
            }
        }
        
        for(auto query:queries)
        	//如果两个节点都存在且在同一棵树上,则直接求值;否则设为-1.0
            if(hash.find(query[0])!=hash.end() 
            	&& hash.find(query[1])!=hash.end() 
            	&& find_parent(hash[query[0]]) == find_parent(hash[query[1]]))
                res.push_back(hash[query[0]]->val / hash[query[1]]->val);
            else
                res.push_back(-1.0);
        
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值