我发现了棋子的可能移动并将其存储在以下数组中。
calculate
现在,我需要根据这些动作创建以下路径。
var moves = [ {from: 67 , to:35} , {from: 35 , to:3} , {from: 35 , to:37} , {from: 35 , to:33} , {from: 37 , to:5} , {from: 37 , to:39} , {from: 33 , to:1} ,{from: 39 , to:7} ] ;
我做了一些代码来创建路径数组,但这不是我需要做的工作,请有人帮忙创建路径。
因为没有目的地,所以我不能使用DFS或BFS。
var path1= [{from:67, to:35} , {from:35, to:3}];
var path2= [{from:67, to:35} , {from:35, to:37} , {from:37, to:5} ];
var path3= [{from:67, to:35} , {from:35, to:33} , {from:33, to:1}];
var path4= [{from:67, to:35} , {from:35, to:37} , {from:37, to:39} , {from:39, to:7} ];
以下答案适用于以上示例,但不适用于以下示例
84至52、52至20、52至54、52至50、20至22、20至18、54至22 50至18、22至20、18至20、20至18、20至22
具有以下路径
1)84 52,52 20,20 18
2)84 52,52 20,20 22
3)84 52、52 54、54 22、22 20、20 18
4)84 52,52 50,50 18,18 20,20 22
为此图。
答案 0 :(得分:0)
第一个示例是一个tree traversal问题:找到为其所有叶子(没有子代的后代节点)指定根的每条路径。
要执行遍历,这有助于将树放置成一种形式,从而可以快速查找给定父级的子级。搜索之后,我们需要将结果路径转换为您要求的格式。
这是树:
67
|
35
/ | \
3 37 33
/ \ \
5 39 1
\
7
解决方案与DFS / BFS相同,除了找到叶子节点后不返回,计算返回到根的路径,将其添加到主路径列表中并继续搜索树的其余部分,这一解决方案与之相同。 / p>
const pathsToLeaves = (root, tree) => {
const parent = {root: null};
const stack = [root];
const paths = [];
while (stack.length) {
let curr = stack.pop();
if (curr in tree) {
for (const child of tree[curr]) {
stack.push(child);
parent[child] = curr;
}
}
else {
const path = [];
while (curr) {
path.unshift(curr);
curr = parent[curr];
}
paths.push(path);
}
}
return paths;
};
const movesToTree = moves =>
moves.reduce((a, e) => {
if (!(e.from in a)) {
a[e.from] = [];
}
a[e.from].push(e.to);
return a;
}, {})
;
const pathsToMoves = paths =>
paths.map(f => f.reduce((a, e, i) => {
if (a === null) {
a = [{from: e}];
}
else if (i < f.length - 1) {
a[a.length-1].to = e;
a.push({from: e});
}
else {
a[a.length-1].to = e;
}
return a;
}, null))
;
const getPaths = (from, moves) =>
pathsToMoves(pathsToLeaves(from, movesToTree(moves)))
;
const moves = [
{from: 67, to: 35},
{from: 35, to: 3},
{from: 35, to: 37},
{from: 35, to: 33},
{from: 37, to: 5},
{from: 37, to: 39},
{from: 33, to: 1},
{from: 39, to: 7}
];
console.log(getPaths(67, moves));
您发布的第二个示例是循环多重图。仍然可以获取您请求的所有路径,但是该算法比树形版本的效率低很多,这是因为预处理需要删除多图中的平行边,在转换为所需格式或从所需格式转换以及在复制过程中进行数组/对象复制遍历。可以使用各种方法来优化其中许多减速带,但这是一个基本版本:
const pathsFrom = (src, graph) => {
const stack = [[src, [], {}]];
const paths = [];
while (stack.length) {
const [curr, path, visited] = stack.pop();
if (curr in graph && !(curr in visited)) {
visited[curr] = 1;
path.push(curr);
let pathFollowed = false;
for (const neighbor of graph[curr]) {
if (!(neighbor in visited)) {
pathFollowed = true;
const visitedCpy = Object.keys(visited).reduce((a, e) => {
a[e] = visited[e];
return a;
}, {});
stack.push([neighbor, path.slice(0), visitedCpy]);
}
}
if (!pathFollowed) {
paths.push(path);
}
}
else {
paths.push(path.concat(curr));
}
}
return paths;
};
const movesToGraph = moves =>
moves.reduce((a, e) => {
if (!(e.from in a)) {
a[e.from] = [];
}
a[e.from].push(e.to);
return a;
}, {})
;
const pathsToMoves = paths =>
paths.map(f => f.reduce((a, e, i) => {
if (a === null) {
a = [{from: e}];
}
else if (i < f.length - 1) {
a[a.length-1].to = e;
a.push({from: e});
}
else {
a[a.length-1].to = e;
}
return a;
}, null))
;
const dedupe = a =>
Object.values(a.reduce((a, e) => {
const key = `${e.from} ${e.to}`;
if (!(key in a)) {
a[key] = e;
}
return a;
}, {}))
;
const getPaths = (from, moves) =>
pathsToMoves(pathsFrom(from, movesToGraph(dedupe(moves)), [], []))
;
[
[
{from: 67, to: 35},
{from: 35, to: 3},
{from: 35, to: 37},
{from: 35, to: 33},
{from: 37, to: 5},
{from: 37, to: 39},
{from: 33, to: 1},
{from: 39, to: 7}
],
[
{from: 84, to: 52},
{from: 52, to: 20},
{from: 52, to: 54},
{from: 52, to: 50},
{from: 20, to: 22},
{from: 20, to: 18},
{from: 54, to: 22},
{from: 50, to: 18},
{from: 22, to: 20},
{from: 18, to: 20},
{from: 20, to: 18},
{from: 20, to: 22},
]
].forEach(test => console.log(getPaths(test[0].from, test)));