目录
题目:
示例:
分析:
代码:
题目:
示例:
分析:
题目给我们多个二维数组形式的除法等式,在二维数组里有两个字符串,表示同名的未知数,另一个数组中对应索引的值就是这两个未知数相除的结果。然后再给我们一个以两个未知数为一组的二维数组,让我们根据之前的未知数等式来解开这些未知数相除的结果。
那么乍一看还挺唬人,传入的参数比较多,测试用例看着也比较花。
其实就是让我们解出等式的值,解不出的置为-1。
那么首先我们根据给的条件,只能得出两个未知数的倍数关系,因为未知数a除未知数b等于一个值n,那么未知数a就是等于n倍的未知数b,而未知数b就等于是1/n倍的未知数a。
所以要解未知数等式,我们就需要寻找这两个位置共同拥有的一个未知数的倍数关系,例如一个a等于两个b,一个b等于三个c,那么一个a就等于6个c。
我们先定义一个map,键为未知数,值为pari<string,int>类型,表示未知数是n倍的另一个未知数。
遍历完题目给的等式,我们就把能获取到的倍数关系都存到map里了。
接着就是开始求解等式,因为我们存倍数关系是双向存的,所以在求解的时候,我们只需要将未知数等式中的任意一个未知数转换为另一个未知数即可,例如代码里我将第一个未知数转为n个第二个未知数,那么除法求值的结果就是n。
那最后的问题就是我们应该如何将未知数转变为另一个未知数,这里我们需要用到DFS,去寻找每一个和第一个未知数有关的倍数未知数,同时再从这些有关的倍数未知数里再去寻找和目标未知数有倍数关系的未知数,我们这边要注意的是,这样寻找绝对会重复寻找同一个未知数进而进入死循环,因此我们要用一个set来存放已经被我们查找过的未知数,如果查找过我们就不再重复去查找了。
如果最后找不到对应的倍数关系,我们就返回double类型的最小值来表示找不到,因为大概率是不会刚好有未知数的倍数关系就是double类型的最小值的,所以我们用它来做标记。
最后将最终结果返回即可。
代码:
lass Solution {
public:
unordered_map<string,vector<pair<string,double>>>M; //记录每个字母的等价字母
double Find(string root,string target,unordered_set<string> &pass){
for(auto &v:M[root]){ //寻找未知数是否和目标未知数有倍数关系
if(pass.find(v.first)==pass.end()){ //如果不在去重集合里就开始寻找.
if(v.first==target) return v.second;
pass.insert(v.first);
double num=Find(v.first,target,pass);
if(num!=DBL_MIN) return num*v.second;
}
}
return DBL_MIN; //找不到目标未知数的相关倍数就返回double的最小值来作为找不到的标记
}
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
for(int i=0;i<equations.size();i++){ //遍历关系,塞进关系表里
if(M.find(equations[i][0])==M.end()){ //如果关系表里没有对应的未知数,那么存入自身,倍数为1
M.insert(make_pair(equations[i][0],vector<pair<string,double>>(1,make_pair(equations[i][0],1))));
}
if(M.find(equations[i][1])==M.end()){
M.insert(make_pair(equations[i][1],vector<pair<string,double>>(1,make_pair(equations[i][1],1))));
}
M[equations[i][0]].push_back(make_pair(equations[i][1],values[i])); //将倍数关系存入
M[equations[i][1]].push_back(make_pair(equations[i][0],1/values[i]));
}
vector<double>res(queries.size(),-1);
unordered_set<string>pass; //用于去重,不在关系表里重复寻找一个未知数
for(int i=0;i<queries.size();i++){
//如果关系表里没有要求的未知数就跳过
if(M.find(queries[i][0])==M.end()||M.find(queries[i][1])==M.end()) continue;
pass.clear(); //每次都清空一下去重集合
double num=Find(queries[i][0],queries[i][1],pass); //寻找第一个未知数是第二个未知数的几倍
if(num!=DBL_MIN) res[i]=num;
}
return res;
}
};