【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)

时间: 2024-10-05 22:42:05

【Graph】399. Evaluate Division(Medium)的相关文章

【leetcode】:Evaluate Reverse Polish Notation (python)

逆波兰式的求解,建立一个类栈容器,遍历给定的逆波兰表达式,遇到数字就push, 遇到操作符就进行出栈,连续出两次,因为给定的四则运算符都是双目的,这里注意下这两个操作数的先后顺序,因为对于加法和乘法没关系,但是对于减法和除法是有先后关系的.然后进行相应的运算,将结果push进栈中. 这里附带说明下python中进行除法运算与c,java系列中的除法的不同,就是向下取整的问题.这种不同表现在两个操作数符号不同时的情况. 在c 中 3 / -5 = 0,但是在python中, 结果却为 - 1.这种

【BZOJ4421】[Cerc2015] Digit Division 动态规划

[BZOJ4421][Cerc2015] Digit Division Description 给出一个数字串,现将其分成一个或多个子串,要求分出来的每个子串能Mod M等于0. 将方案数(mod 10^9+7) Input 给出N,M,其中1<=N<=300 000,1<=M<=1000 000. 接下来一行,一个数字串,长度为N. Output 如题 Sample Input 4 2 1246 Sample Output 4 题解:如果一个前缀a%m==0,另一个长一点的前缀b

【题解】HDU5845 Best Division (tri树)

[题解]HDU5845 Best Division (tri树) 题意:给定你一个序列(三个参数来根),然后请你划分子段.在每段子段长度小于等于\(L\)且子段的异或和\(\le x\)的情况下最大化分出子段的个数 区间/子段/序列这种东西一大性质就是右端点之后与前面无关. \(dp(i)\)表示上一个右端点是\(i\)且前面分出来的子段都满足条件的最多子段个数. 直接转移\(O(n^2)\)考虑优化这个东西,子段转前缀和是应该记起来的套路,现在问题就是变成查询两个前缀和的异或值是否满足条件.

【BZOJ]】1385 [Baltic2000]Division expression

[算法]欧几里德算法 [题解]紫书原题 #include<cstdio> #include<algorithm> using namespace std; const int maxn=10010; int T,t,n,a[maxn]; int gcd(int a,int b) {return b==0?a:gcd(b,a%b);} int main() { scanf("%d",&T); for(int i=1;i<=T;i++) { scanf

399. Evaluate Division

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 =

LeetCode 399. Evaluate Division

原题链接在这里:https://leetcode.com/problems/evaluate-division/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 a

[LeetCode] 399. Evaluate Division Java

题目: 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 /

【leetcode】553. Optimal Division

题目如下: 解题思路:这是数学上的一个定理.对于x1/x2/x3/..../xN的序列,加括号可以得到的最大值是x1/(x2/x3/..../xN). 代码如下: class Solution(object): def optimalDivision(self, nums): """ :type nums: List[int] :rtype: str """ if len(nums) == 1: return str(nums[0]) elif

【LeetCode】Clone Graph 解题报告

[题目] Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. OJ's undirected graph serialization: Nodes are labeled uniquely. We use # as a separator for each node, and , as a separator for node label and each