97 lines
4.0 KiB
JavaScript
97 lines
4.0 KiB
JavaScript
/**
|
||
* @param {string[][]} equations
|
||
* @param {number[]} values
|
||
* @param {string[][]} queries
|
||
* @return {number[]}
|
||
*/
|
||
const calcEquation = function (equations, values, queries) {
|
||
|
||
};
|
||
|
||
/*
|
||
思路:通过equations和values建立一张有权图edges:[[[1, 2],...], [[2, 3],...]],在这里使用邻接表的方式表示,edges表示的是0号顶点可以到一号顶点
|
||
并且权值为2,1顶点到2号顶点的权值是3,如果0号顶点表示a,1号顶点表示b,2号顶点表示c,那么这个图在这个题目里面的意思就是,a/b=2,b/c=2,如果要我们,
|
||
求a/c的值不就是把a->b->c这个路径里面的权值相乘吗?所以这个题目可以分为下面几步:
|
||
步骤:
|
||
1.通过equations,values建立有权图edges
|
||
2.遍历queries,比如要我们求a/e,那么我们就从a为起点出发,开始广度优先遍历,知道找到a->e的路径,之后加权(相乘),如果没找到,就是-1
|
||
*/
|
||
function f1(equations, values, queries) {
|
||
// Step 1: 给每个变量编号,变量名映射到编号
|
||
let nvars = 0; // 变量的数量
|
||
const variables = new Map(); // 存储变量名到编号的映射
|
||
|
||
// 处理 equations,给每个变量一个唯一的编号
|
||
const n = equations.length;
|
||
for (let i = 0; i < n; i++) {
|
||
// 如果变量没有编号,就给它一个编号
|
||
if (!variables.has(equations[i][0])) {
|
||
variables.set(equations[i][0], nvars++);
|
||
}
|
||
if (!variables.has(equations[i][1])) {
|
||
variables.set(equations[i][1], nvars++);
|
||
}
|
||
}
|
||
|
||
// Step 2: 创建图结构,存储每个节点与其他节点的比值
|
||
const edges = new Array(nvars).fill(0); // 创建一个数组来存储每个节点的邻接点和比值
|
||
for (let i = 0; i < nvars; i++) {
|
||
edges[i] = []; // 初始化每个节点的邻接表
|
||
}
|
||
|
||
// 遍历 equations,构建图,每条边的权值是它们之间的比值
|
||
for (let i = 0; i < n; i++) {
|
||
const va = variables.get(equations[i][0]); // 获取变量 a 的编号
|
||
const vb = variables.get(equations[i][1]); // 获取变量 b 的编号
|
||
edges[va].push([vb, values[i]]); // a → b 的比值
|
||
edges[vb].push([va, 1.0 / values[i]]); // b → a 的比值是 1 / (a → b)
|
||
}
|
||
|
||
// Step 3: 处理查询,计算每个查询的结果
|
||
const queriesCount = queries.length; // 查询的数量
|
||
const ret = []; // 存储每个查询的结果
|
||
|
||
for (let i = 0; i < queriesCount; i++) {
|
||
const query = queries[i]; // 当前查询
|
||
let result = -1.0; // 默认结果为 -1.0,表示无法计算
|
||
|
||
// 只有当查询中的两个变量都存在时,才进行计算
|
||
if (variables.has(query[0]) && variables.has(query[1])) {
|
||
const ia = variables.get(query[0]); // 获取查询中第一个变量的编号
|
||
const ib = variables.get(query[1]); // 获取查询中第二个变量的编号
|
||
|
||
// 如果两个变量是同一个,直接返回 1.0
|
||
if (ia === ib) {
|
||
result = 1.0;
|
||
} else {
|
||
// Step 4: 使用 DFS 或 BFS 遍历图,查找从 ia 到 ib 的比值
|
||
const points = []; // 存储当前正在遍历的节点
|
||
points.push(ia); // 从 ia 开始遍历
|
||
|
||
const ratios = new Array(nvars).fill(-1.0); // 存储每个节点的比值,初始值为 -1.0,表示不可达
|
||
ratios[ia] = 1.0; // 起点 ia 到 ia 的比值是 1.0
|
||
|
||
// 使用 DFS 方式遍历图
|
||
while (points.length && ratios[ib] < 0) {
|
||
const x = points.pop(); // 从栈中取出一个节点
|
||
// 遍历当前节点的所有邻接点
|
||
for (const [y, val] of edges[x]) {
|
||
// 如果邻接点 y 尚未访问过(ratios[y] < 0)
|
||
if (ratios[y] < 0) {
|
||
ratios[y] = ratios[x] * val; // 更新 y 的比值
|
||
points.push(y); // 将 y 加入栈中继续遍历
|
||
}
|
||
}
|
||
}
|
||
result = ratios[ib]; // 查询的结果是 ib 到达的比值
|
||
}
|
||
}
|
||
|
||
// 将当前查询的结果存入结果数组
|
||
ret[i] = result;
|
||
}
|
||
|
||
// 返回所有查询的结果
|
||
return ret;
|
||
}
|