我有一个棘手的逻辑问题,我正在尝试创建一个算法来解决它,但我正在努力解决它。
考虑这些数据:
A to B
A to C
A to D
A to E
B to C
B to D
B to E
C to D
C to E
D to E
正如您所看到的,这有效地产生了如下模型:A - B - C - D - E
你只能向一个方向前进,(从左到右)我想写的是一个可以计算出2点之间所有可能组合的算法,即
如果我想从A
转到E
,所有可能的组合都是这样的:
A - E
A - D - E
A - C - E
A - B - E
A - C - D - E
A - B - D - E
A - B - C - E
A - B - C - D - E
我认为就是这样。
有人可以帮我解决这个问题吗?
答案 0 :(得分:3)
首先,考虑一下如何表示单个“跳”:每个节点都需要一个相邻节点的列表。首先构建这些节点。
您还需要一种从节点池中查找节点的方法(按名称?)。也许把它们放在地图上?
一个暴力算法将从所请求的节点开始并递归跟踪所有跳,观察循环,直到到达请求的端,传递List - 使用它作为下推堆栈,来记录路径。每次到达请求的结束时,将列表的内容保存到Path集合。如果你遇到了死胡同(没有链接转到请求的结尾),请在递归中备份并继续。
根据您对速度的需求,您可以扩展数据结构以保留一些预先计算的路径。
尝试使用伪代码然后使用Java。
答案 1 :(得分:2)
您的问题最好说明如下:“对于给定的有向图,列出可以从某个节点转到另一个节点的所有可能路径。”请参阅Graph Algorithm To Find All Connections Between Two Arbitrary Vertices
你可以用递归来解决它:
Paths(NodeSequence start, Node finish, ListOfNodeSequences result)
将一个空白的节点序列列表作为第三个参数,并且可以通过Node n
的一跳到达的每个start
添加start
+ {{ 1}}如果n
为result
,则为n
,否则将finish
作为第一个参数调用Paths
。
递归可能不一定是解决此问题的最有效资源的方法,但编码并不是很多工作。上面的结果假设你将初始化一个空的结果变量,它将被递归函数修改而不是被返回,所以它有点奇怪,但我给出的版本应该花费最少的努力。
不完整的解决方案(省略不相关的实施细节):
start + n
public class Node {
public String name;
public boolean Equals(Node other) {
throw new NotImplementedException();
}
};
public class NodeSequence {
private ArrayList<Node> nodes;
public NodeSequence() {
nodes = new ArrayList<Node>();
}
public NodeSequence Plus(Node n) {
// Returns this NodeSequence with n appended to the end
throw new NotImplementedException();
}
public Node Last() {
throw new NotImplementedException();
}
}
public void paths(NodeSequence start, Node finish, ArrayList<NodeSequence> results) {
Node startNode = NodeSequence.Last();
ArrayList<Node> nextStops;
// Populate nextStops with every node that is directly after startNode
// Recursive block
for (Node n : nextStops) {
if (n.Equals(finish))
results.Add(start.Plus(n));
else
Paths(start.Plus(n), finish, results);
}
}
ArrayList<NodeSequence> findAllPaths(Node start, Node finish) {
ArrayList<NodeSequence> allPaths = new ArrayList<NodeSequence>();
// This line will take a while
paths(start, finish, allPaths);
return allPaths;
}
会给你结果。
答案 2 :(得分:1)
我认为逻辑可能如下:
维护一个列表/数组,例如
char[] chars = {'A','B', 'C', 'D','E'};
为每个范围打印实施2个嵌套for循环,
for begin =0 to end
collect chars[beign]
for indx end -begin to end
collect chars[indx]
我认为这样做会。
一个示例逻辑如下:
char[] chars = {'A','B', 'C', 'D','E'};
List<Character> charList = new ArrayList<Character>();
for (int begin=0; begin <chars.length; begin++){
for (int index=begin; index <chars.length; index++){
charList.add(chars[begin]);
for (int indx1=chars.length-index; indx1 <chars.length-begin; indx1++){
charList.add(chars[indx1+begin]);
}
System.out.println(charList);
charList.clear();
}
}
哪个应该打印结果为:
[A]
[A, E]
[A, D, E]
[A, C, D, E]
[A, B, C, D, E]
[B]
[B, E]
[B, D, E]
[B, C, D, E]
[C]
[C, E]
[C, D, E]
[D]
[D, E]
[E]