【发布时间】:2015-02-05 03:14:28
【问题描述】:
我在面试时遇到了这个问题:
给定一个无向图(由其对应的边描述),我如何找到可能的三角形的数量?
示例: 对于:{(0,1), (2,1), (0,2), (4,1)} 答案将是:1。
我想到了一个算法,但在途中遇到了Java技术问题(而且我知道可能还有其他更有效的算法,我的算法的正确性和效率不是重点,技术问题在路上是)。
我的算法是这样的: 定义一个 Hashmap:Map 。地图的键 Couple 是一个基本上包含两个点的对象:起点(例如顶点“0”)和出口点(例如顶点“1”)。地图的整数值是我从开始顶点到结束顶点所经过的边数。 即对于边缘 (0,1),地图中将有一个条目显示:(new Couple(0,1),1); 对于这 2 条边 (0,1),(1,2),地图中将有一个条目,例如:(new couple(0,2),2) 因为我们可以通过遍历这 2 条从 0 到 2边缘。
我的想法是在地图上开始迭代并检查每个顶点是否可以连接(意味着它的出口点与其他顶点的起点匹配,反之亦然)。如果是这样,则创建一个适当的新条目,其边数为其他顶点数+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);
}
}
【问题讨论】:
-
我不确定
entrySet的iterator是否支持remove,但如果支持,这是首选方式。 (对不起,这只是为了删除。对于添加,您必须执行@PatrickChan 建议的操作。) -
我测试了代码,它没有抛出 ConcurrentModificationException。显示您如何调用该方法,以便我重现异常。
-
System.out.println(NumberOfTriangles(new Couple[] { new Couple(0, 1), new Couple(2, 1), new Couple(0, 2), new Couple(4, 1) }));
-
Couple 类现已添加到原始评论中
标签: java algorithm loops map hashmap