前一段时间我遇到了这个问题,而今天仍然困扰着我。希望能得到一些答案。
如果您有以下课程,
class Node {
String unqId;
Node[] neighbors;
Boolean isBlack;
}
以及这些节点的集合,如下所示。您将如何编写遍历节点并输出连接的黑色节点的所有可能组合的算法。
因此,此示例的答案是
[a], [b], [d], [f], [h], [i],
[a, b], [a, d], [f, i], [h, i],
[d, a, b], [h, i, f]
我暂时将其保持简单,但是从理论上讲,您可能会拥有四个以上邻居的节点...
答案 0 :(得分:1)
我附加了蛮力解决方案(O(m*n^2*2^n)
),其中输入是表示图的邻接表,输出是表示连接的节点的字符串数组的集合。
n是节点数,m是连接的节点数。
一个快速的解释是遍历邻接列表(O(n)
),并且每个黑色节点都作为一个元素数组添加到输出中。然后遍历所有该黑色节点的邻居(O(m)
),如果它们是黑色的,则将它们成对添加到输出中。
现在是检查节点是否为黑色的固定时间。
最后,在while循环中,检查是否有新数组添加到输出中,遍历输出集合,并检查每个数组中的每个节点是否有黑色邻居,这些邻居会形成一个数组,但该数组中尚不存在输出。如果是,请将其添加到输出集合。如果在while循环的此迭代过程中向输出添加了新数组,则它将再次循环,否则将返回输出集合。
这是O(m*n^2*2^n)
时间,因为输出中可能有2^n
个数组,每个数组都有n
个元素,每个元素最多可以有m
个邻居。 while循环最多重复n
次。
编辑:@Primusa指出了输出集合中元素的正确数量。
伪代码蛮力实施:
output findBlackCombos(AdjacencyList adjList) {
// n is the number of nodes and m is number of neighbors
// Output is a collection of arrays of the connected black nodes
Collection<Array<String>> output;
// O(m+n) because this is the cost to search through adjacency list
foreach (node in adjList) {
if (node.isBlack)
output.add(new {node.unqID});
foreach (neighbor in adjList[node.unqID]) {
if (node.isBlack)
output.add(new {node.unqID, neighbor.unqId});
}
}
Boolean elementsBeingAdded = true;
// O(m*n^2*2^n)
while(elementsBeingAdded) {
elementsBeingAdded = false;
foreach(array in output) {
foreach (node in array) {
foreach (neighbor in adjList[node.unqID]) {
if (!output.Contains({array, neighbor.unqID})) {
output.add(new {array, neighbor.unqID});
elementsBeingAdded = true;
}
}
}
}
}
return output;
}
答案 1 :(得分:1)
使用BFS或DFS查找已连接的黑色组件(忽略导致白色节点的边缘)。然后,对于这些组件中的每个组件,找到连接的诱导子图。对于大小为r的分量,可以在O(2 ^ r)中完成,因此在所有节点均为黑色的最坏情况下,这是O(2 ^ n)。此链接后面的已接受答案中说明了此步骤的详细信息。