【问题标题】:Finding a Common Element of 4 Elements找到 4 个元素的共同元素
【发布时间】:2014-05-02 14:24:06
【问题描述】:

我有一张地图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]

在本例中,45 出现在 adjacencyLists 的第一个和第三个条目的值中。

因此,写一个函数findCommon(1,3) 应该给我[4 5]
同样,findCommon(1,5) 应该返回 null,因为 '2' 是唯一常见的元素,并且不在 specialNodes 中。

【问题讨论】:

  • findCommon(1,3) 给出[4 5]。那么specialNodes有什么用呢?
  • 它4和5都在specialNodes
  • 他们是TreeSets。我假设它们是排序的。不过,我可以对它们进行排序。这需要O(nlogn) 时间。没问题。
  • 没有。 TreeMap 集的值。他们排序了吗?
  • 是的,我将元素添加为put(adjacencyLists.size(), set);

标签: java map set graph-theory


【解决方案1】:

这是一个逐步的过程。

  1. 从键中获取两个值。 O(logn)
  2. 对它们进行排序。 O(nlogn)
  3. 找到common elementsO(m+n)
  4. specialNodes 中搜索共同元素。 O(m+n)

因此最坏情况时间复杂度 = O(nlogn)

【讨论】:

    【解决方案2】:

    所以,如果我理解正确,您已经为每个 Integer 设置了一个集合,列出了它的邻接关系?

    我能看到的最简单有效的方法是使用另一个 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;
    

    【讨论】:

      【解决方案3】:

      不是 100% 确定您的意思,但这是我的想法。一种可能的方法是使用像 BFS 这样的搜索算法。由于所有这四个节点都必须有一个公共节点,这意味着如果您使用四个节点中的一个作为根节点并在三个节点中相互搜索。如果对所有三个的搜索都成功,则它们必须具有一个公共节点。

      【讨论】:

        【解决方案4】:

        显而易见的解决方案是制作一个 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;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-26
          • 2015-12-16
          • 2011-04-11
          • 2016-07-06
          • 1970-01-01
          相关资源
          最近更新 更多