我在面试时遇到过这个问题:
给定一个无向图(由相应边描述),我如何找到可能的三角形数?
实施例: for:{(0,1),(2,1),(0,2),(4,1)}答案是:1。
我想到了一个算法,但在途中遇到了Java技术问题(而且我知道可能有更高效的其他算法,我的算法的正确性和有效性不是重点,技术问题在路上是)。
我的算法是这样的: 定义一个Hashmap:Map<夫妇,整数取代。地图的关键是Couple,它基本上包含两个点:起点(比如顶点'0')和出点(比如顶点'1')。地图的整数值是我从起始顶点到终点顶点的边数。 即对于边缘(0,1),地图中将有一个条目表示:( new Couple(0,1),1); 对于这两个边(0,1),(1,2),地图中会有一个条目,如:( new couple(0,2),2)因为我们可以通过遍历这两个从0到2边缘。
我的想法是开始在地图上迭代,并为每个顶点检查它是否可以连接(意味着它的出口点与其他顶点的起点相匹配,反之亦然)。如果是这样,请创建一个合适的新entrey,其边缘数为+ 1。最后,我想计算有多少对夫妇以相同的数字开头和结尾,大小为3(意味着创建一个三角形)。
问题在于,当我在地图上迭代时,我也改变了它(添加新条目,每次我找到连接到另一个的新边缘)。这导致我得到一个“java.util.ConcurrentModificationException”。
我想知道是否有人有办法解决这个问题,此外有人可以解释如何在将来克服这样的问题。 非常感谢!
public static int NumberOfTriangles(Couple[] nodes) {
Map<Couple, Integer> map = new HashMap<>();
int x1 = 0, y1 = 0, counter = 0;
int x2 = 0, y2 = 0;
for (int i = 0; i < nodes.length; i++) {
x1 = nodes[i].getStart();
y1 = nodes[i].getEnd();
map.put(new Couple(x1, y1), 1);
map.put(new Couple(y1, x1), 1);
}
for (int i = 0; i < nodes.length; i++) {
x1 = nodes[i].getStart();
y1 = nodes[i].getEnd();
Iterator<Entry<Couple, Integer>> entries = map.entrySet()
.iterator();
while (entries.hasNext()) {
Entry<Couple, Integer> thisEntry = (Entry<Couple, Integer>) entries
.next();
x2 = thisEntry.getKey().getStart();
y2 = thisEntry.getKey().getEnd();
if (y1 == x2) {
int value = map.get(new Couple(x1, y1));
if (value < 3) {
value++;
if ((value == 3) && (x1 == y1)) {
counter++;
}
map.put(new Couple(x1, y2), value + 1);
}
}
if (x1 == y2) {
int value = map.get(new Couple(x2, y1));
if (value < 3) {
value++;
if ((value == 3) && (x1 == y1)) {
counter++;
}
map.put(new Couple(y1, x2), value + 1);
}
}
if (y1 == y2) {
int value = map.get(new Couple(x1, x2));
if (value < 3) {
value++;
if ((value == 3) && (x1 == y1)) {
counter++;
}
map.put(new Couple(x1, x2), value + 1);
}
}
if (x1 == x2) {
int value = map.get(new Couple(y1, y2));
if ((value == 3) && (y1 == y2)) {
value++;
if (value == 3) {
counter++;
}
map.put(new Couple(y1, y2), value + 1);
}
}
}
}
return counter;
}
情侣
public class Couple {
private int start;
private int end;
public Couple(int start, int end) {
this.start = start;
this.end = end;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
@Override
public boolean equals(Object other) {
if (other == this) {
return true;
} else {
return ((((Couple) other).getStart() == start) && ((Couple) other)
.getEnd() == end);
}
}
@Override
public int hashCode() {
return (start + end);
}
}
答案 0 :(得分:0)
使用另一个Vector来存储要修改的值,并在迭代器循环
之后执行答案 1 :(得分:0)
您可以通过将 HashMap 更改为 ConcurrentHashMap 来修复该异常。 并改变每一个
int value = map.get(new Couple(x1, y1));
if (value < 3) {
到
Integer value = map.get(new Couple(x1, y1));
if (value != null && value < 3) {
这不会抛出ConcurentModificationException,但它不会找到任何三角形,因为我认为你的算法有误。 这是一个有用的新算法:
夫妇:
public class Couple {
private int start;
private int end;
public Couple(int start, int end) {
this.start = start;
this.end = end;
}
public int getStart() {
return start;
}
public int getEnd() {
return end;
}
}
节点
import java.util.HashSet;
import java.util.Set;
public class Node {
private int value;
private Set<Node> adjacentNodes = new HashSet<Node>();
public Node(int x) {
value = x;
}
public void addAdjacentNode(Node node) {
adjacentNodes.add(node);
}
public int getValue() {
return value;
}
public void setValue(int values) {
this.value = values;
}
public Set<Node> getNodes() {
return adjacentNodes;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + value;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (value != other.value)
return false;
return true;
}
}
三角
public class Triangle {
private Set<Integer> nodes = new HashSet<Integer>();
public Triangle(Node... node ) {
for (Node node2 : node) {
nodes.add(node2.getValue());
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((nodes == null) ? 0 : nodes.hashCode());
return result;
}
@Override
public String toString() {
return "Triangle [nodes=" + nodes + "]";
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Triangle other = (Triangle) obj;
if (nodes == null) {
if (other.nodes != null)
return false;
} else if (!nodes.equals(other.nodes))
return false;
return true;
}
}
主要
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) {
Set<Triangle> foundTriangles = new HashSet<Triangle>();
Map<Integer, Node> graph = new HashMap<Integer, Node>();
Couple[] a = new Couple[] { new Couple(0, 1),
new Couple(2, 1),
new Couple(0, 2),
new Couple(4, 1) };
// build graph
for (Couple couple : a) {
int start = couple.getStart();
Node node1 = graph.get(start);
if (node1 == null) {
node1 = new Node(start);
graph.put(start, node1);
}
int end = couple.getEnd();
Node node2 = graph.get(end);
if (node2 == null) {
node2 = new Node(end);
graph.put(end, node2);
}
node1.addAdjacentNode(node2);
node2.addAdjacentNode(node1);
}
// search for triangles in the graph
for (Node root : graph.values()) {
Set<Node> nodes = root.getNodes(); // A
for (Node root2 : nodes) { // B
if (!root2.equals(root)) { // prevent going back
Set<Node> nodes2 = root2.getNodes();
for (Node root3 : nodes2) { // C
if (!root3.equals(root2)) {
Set<Node> nodes3 = root3.getNodes();
for (Node node4 : nodes3) {// A
if (!node4.equals(root3)) {
if (node4.equals(root)) {
// String message =
// MessageFormat.format(
// "Found triangle: {0}{1}{2}",
// root.getValue(),
// root2.getValue(),
// root3.getValue());
// System.out.println(message);
Triangle t = new Triangle(root,
root2,
root3);
foundTriangles.add(t);
}
}
}
}
}
}
}
}
System.out.println(foundTriangles);
}
}
输出就像
[Triangle [nodes=[0, 1, 2]]]
如果使用MessageFormat删除对行的注释,将会看到更详细的输出
Found triangle: 012
Found triangle: 021
Found triangle: 120
Found triangle: 102
Found triangle: 210
Found triangle: 201
[Triangle [nodes=[0, 1, 2]]]
这是因为算法找到了相同的三角形6次。