我有一张地图TreeMap<Integer, Set<Integer>> adjacencyLists
和一个整数集TreeSet<Integer> specialNodes
。
地图代表图表的邻接列表。
我想从adjacencyLists
中挑选密钥,并在specialNodes
中找出它们之间是否存在共同的密钥。
有没有办法有效地做到这一点?
示例:
adjacencyLists
如下:
[1, [2 3 4 5]]
[2, [1 5]]
[3, [1 4 5]]
[4, [1 3]]
[5, [1 2 3]]
和specalNodes
如下:
[1 3 4 5]
在此示例中,4
的第一个和第三个条目的值中包含5
和adjacencyLists
。
因此,编写一个函数findCommon(1,3)
应该给我[4 5]
同样,findCommon(1,5)
应返回null
,因为&#39; 2&#39;是唯一的常见元素,不在specialNodes
。
答案 0 :(得分:2)
这是一步一步的过程。
O(logn)
。O(nlogn)
。O(m+n)
。specialNodes
中搜索常见元素。 O(m+n)
。因此,最坏情况时间复杂度= O(nlogn)
。
答案 1 :(得分:1)
所以,如果我正确理解你已经为每个整数列出了它的邻接,那么它就已经有了一套?
我能看到的最简单有效的方法是使用另一个Set。设置非常快,用于检查它们是否已包含值。
Set<Integer> adjacent = new HashSet<>();
for (Integer i: toCheck) {
int oldCount = adjacent.size();
Set<Integer> check = adjacencyLists.get(i);
adjacent.addAll(check);
if (adjacent.size() != oldCount+check.size()) {
// Duplicate found
return true;
}
}
return false;
如果您需要知道公共的标识,那么通过执行单独的添加调用而不是执行addAll来循环,并检查每个添加是否成功。实际上这可能更有效,因为不需要进行大小检查:
Set<Integer> adjacent = new HashSet<>();
for (Integer i: toCheck) {
Set<Integer> check = adjacencyLists.get(i);
for (Integer c: check)
if (!adjacent.add(c)) {
// Duplicate found
return c;
}
}
return null;
刚看到普通会员完整名单的请求:
Set<Integer> adjacent = new HashSet<>();
Set<Integer> results = new HashSet<>();
for (Integer i: toCheck) {
Set<Integer> check = adjacencyLists.get(i);
for (Integer c: check)
if (!adjacent.add(c)) {
// Duplicate found
results.add(c);
}
}
return results;
答案 2 :(得分:1)
不是100%肯定你的意思,但这是我的想法。一种可能的方法是使用像BFS这样的搜索算法。由于所有这四个节点必须具有一个公共节点,因此意味着您将四个节点中的一个用作root用户并搜索三个节点中的每个节点。如果搜索所有三个成功,则它们必须具有一个公共节点。
答案 3 :(得分:0)
显而易见的解决方案是创建specialNodes的副本,然后在您正在考虑的所有集合上调用其方法retainAll,结果集合包含公共节点。你试过吗?它不够有效吗?
代码:
Set findCommons(int a, int b) {
HashSet commonNodes = new HashSet(specialNodes);
commonNodes.retainAll(adjacencyLists.get(a));
commonNodes.retainAll(adjacencyLists.get(b));
return commonNodes;
}