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>
.
这个问题比较容易想到的方法是建立一个有向图,弧的起点对应被除数,终点对应除数,弧上的值对应起点比终点的商,要得到x/y的值,只要找到从x到y的一条路径,将路径上的值相乘即可。想法比较简单,不过程序会有些复杂,目前我的程序如下:(里面还有一些问题没来得及修改)
#include<iostream>
#include <queue>
#include<vector>
#include<algorithm>
#include<numeric>
#include <cstdlib>
#include<string>
using namespace std;
using std::vector;
#define max_vertices_num 20
struct ArcNode//弧
{
int adjvex;//该弧所指的顶点的位置
struct ArcNode *nextarc;//指向下一条弧的指针
double quot;//弧的起点比终点的商
};
struct VNode//头结点
{
string valu;//顶点的值
struct ArcNode *firstarc;//指向第一条从该顶点出发的弧的指针
};
class graph
{
public:
struct VNode vertices[max_vertices_num];
static int vexnum;//结点的个数
graph();
virtual ~graph();
void insertvex(pair<string, string> v,double qu)
{
int i,j;
struct ArcNode *p;
struct ArcNode *q;
//检查图中是否已有v
for(i=0;i<vexnum;i++)
{
if(vertices[i].valu==v.first)
{
for(j=0;j<vexnum;j++)
{
if(vertices[j].valu==v.second)
{
printf("输入相同的比值!\n");
exit(-1);
}
}
vexnum++;
vertices[vexnum-1].valu=v.second;
vertices[vexnum-1].firstarc=NULL;
p=vertices[i].firstarc;
while(p->nextarc!=NULL)
{
p=p->nextarc;
}
q=new ArcNode;
q->adjvex=vexnum-1;
q->nextarc=NULL;
q->quot=qu;
p->nextarc=q;
}
}
if(i==vexnum)
{
vexnum++;
vertices[vexnum-1].valu=v.first;
for(j=0;j<(vexnum-1);j++)
{
if(vertices[j].valu==v.second)
{
q=new ArcNode;
q->adjvex=j;
q->nextarc=NULL;
q->quot=qu;
vertices[vexnum-1].firstarc=q;
}
}
if(j=(vexnum-1))
{
q=new ArcNode;
q->adjvex=vexnum;
q->nextarc=NULL;
q->quot=qu;
vertices[vexnum-1].firstarc=q;
vexnum++;
vertices[vexnum-1].valu=v.second;
vertices[vexnum-1].firstarc=NULL;
}
}
}
double BFSTraverse(pair<string, string> p);
};
double graph::BFSTraverse(pair<string, string> p)
{
// 按广度优先非递归遍历图G。使用辅助队列Q。
int v,w;
queue<string> Q;
string u;
int visited[max_vertices_num];
int start,pr;
double result=1.0;
int pre[max_vertices_num];
struct ArcNode *edg;
for (v=0; v<vexnum; ++v) visited[v] = 0;
for(v=0; v<vexnum; ++v)
{
if(vertices[v].valu==p.first)
{
Q.push(p.first);
visited[v]=1;
start=v;
pr=v;
break;
}
}
while(!Q.empty())
{
u=Q.front();
Q.pop();
for(v=0; v<vexnum; ++v)
{
if(vertices[v].valu==u)
{
edg=vertices[v].firstarc;
while(edg->nextarc!=NULL)
{
if(visited[edg->adjvex]==0)
{
Q.push(vertices[edg->adjvex].valu);
pre[edg->adjvex]=pr;
pr=edg->adjvex;
visited[edg->adjvex]=1;
if(vertices[edg->adjvex].valu==p.second)
break;
}
}
break;
}
}
for(v=0;v<vexnum; ++v)
{
if(vertices[v].valu==p.second)
{
while(pre[v]!=start)
{
edg=vertices[pre[v]].firstarc;
while(edg->adjvex!=v)
edg=edg->nextarc;
result*=edg->quot;
v=pre[v];
}
edg=vertices[start].firstarc;
while(edg->adjvex!=v)
edg=edg->nextarc;
result*=edg->quot;
break;
}
}
}
return result;
}
class Solution :public graph{
public:
vector<double> calcEquation(vector<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries) {
graph G;
vector<double> results;
string temp;
vector<pair<string, string> >::iterator it1=equations.begin();
vector<pair<string, string> >::iterator it2=equations.end();
pair<string, string>e;
int i=0;
for(;it1!=it2;it1++,it2++)
{
if(values[i]!=0)
{
G.insertvex(equations[i],values[i]);
temp=equations[i].first;
equations[i].first=equations[i].second;
equations[i].second=temp;
//equations.swap(equations[i]);
G.insertvex(equations[i],(1/values[i]));
i++;
}
else
{
G.insertvex(equations[i],values[i]);
i++;
}
}
it1=queries.begin();
it2=queries.end();
i=0;
while(it1!=it2)
{
results.push_back(G.BFSTraverse(queries[i]));
i++;
it1++;
}
return results;
}
};