【Graph】399. Evaluate Division(Medium)
#week3#
#from leetcode#
Description
Equations are given in the format A / B = k
, where A
and B
are variables represented as strings, and k
is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0
.
Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].
The input is: vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries
, where equations.size() == values.size()
, and the values are positive. This represents the equations. Return vector<double>
.
According to the example above:
equations = [ ["a", "b"], ["b", "c"] ], values = [2.0, 3.0], queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
Analysis
题目的意思是给我们一些除法等式,让我们通过这些除法等式来求解其他的一些除法式子,输入有等式集,对应等式的值还有查询的等式集。
那么我们应该如何思考这个问题怎么去解决呢?
答案等式只能够在已知的等式推导出来,我们可能直接通过一个等式得到答案,可能是通过几个等式连在一起除下去得到答案;因此我们可以把这个问题想成一个无向图的问题,每一个变量是图中的一个节点,而每一个等式是图中的路径,路径上的权值则是等式的值,为何要想成无向图而不是有向图呢?因为我们式子可以双向推导,另外实际上我们的无向图路径权值不能够只存一个,需要存v->u的权值,还需要有u->v的权值。
想成图之后,我们重新来思考这个问题,求等式的解,那么就是求图中的一个节点是否能够走到另一个节点,如果可以,并求出它们之间的路径的乘积,所以我们这个问题思路就变得很清晰了,那么我们再考虑需要一些什么集合,边集、点集、还有查询集,我们就将最初的equations作为边集,然后再加上相反的边即可,点集在遍历时构建,然后再写一下算法的大概思路如下:
①遍历equations,加入返回边和权重(权重用values数组存储好即可,下标与equations下标一一对应即可),并且将点加入点集;
②遍历queries:
对于每个query:
两点是否在点集中-->no:result=-1,continue继续下一个query;
-->yes
两个点是否相同-->yes:result=1,continue继续;
-->no
从开始点开始做BFS找去终点的路径,如果能够找到则返回权值,如果不能够则result=-1;
于是就可以愉快地编程了~!其实思路是在不断修补完善中的,最开始有的是一个大致框架,然后写的时候发现一些情况漏掉了,再补上去,才把这个算法补成正确完备的算法。
Code
1 #include<vector> 2 #include<string> 3 #include<queue> 4 #include<iostream> 5 using namespace std; 6 class Solution { 7 private: 8 static bool exits(vector<string> vec, string value) { 9 vector<string>::iterator i; 10 for (i = vec.begin(); i != vec.end(); i++) { 11 if (value == (*i)) return true; 12 } 13 return false; 14 } 15 public: 16 vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries) { 17 vector<string> points; 18 int size = equations.size(); 19 for (int i = 0; i < size; i++) { 20 string firstOne = equations[i].first; 21 string secondOne = equations[i].second; 22 //cout << (exits(points, firstOne)) << exits(points, secondOne); 23 if (!exits(points, firstOne)) points.push_back(firstOne); 24 if (!exits(points, secondOne)) points.push_back(secondOne); 25 equations.push_back(make_pair(secondOne, firstOne)); 26 values.push_back(1 / values[i]); 27 } 28 29 vector<double> result; 30 for (int i = 0; i < queries.size(); i++) { 31 string begin = queries[i].first; 32 string end = queries[i].second; 33 34 if (!exits(points, begin) || !exits(points, end)) { 35 result.push_back(-1); 36 continue; 37 } 38 39 if (begin == end) { 40 result.push_back(1); 41 continue; 42 } 43 44 queue<string> que; 45 queue<double> weight; 46 vector<string> gone; 47 que.push(begin); 48 weight.push(1); 49 gone.push_back(begin); 50 double temp = -1; 51 while (!que.empty()) { 52 string point = que.front(); 53 double value = weight.front(); 54 que.pop(); 55 weight.pop(); 56 for (int i = 0; i < equations.size(); i++) { 57 if (equations[i].first == point) { 58 if (equations[i].second == end) { 59 temp = value*values[i]; 60 break; 61 } 62 if (!exits(gone, equations[i].second)) { 63 que.push(equations[i].second); 64 weight.push(value*values[i]); 65 gone.push_back(equations[i].second); 66 } 67 } 68 } 69 if (temp != -1) { 70 break; 71 } 72 } 73 result.push_back(temp); 74 } 75 return result; 76 } 77 };
Run Time:0ms(leetcode test)