【问题标题】:efficient way to do 'contains' between two lists在两个列表之间进行“包含”的有效方法
【发布时间】:2011-08-08 18:27:27
【问题描述】:

我有 2 个整数列表,

l1 = new ArrayList();
l2 = new ArrayList();

我想找出它们中的重复项,我有我惯用的方法:-

for (Integer i : l1)
{
 if(l2.contains(i)){
    System.out.println("Found!");
  } 
}

我听说contains()O(n),我的实现是O(n^2)

有没有更好的方法来做到这一点,(小于O(n^2))?

【问题讨论】:

    标签: java collections arraylist time-complexity


    【解决方案1】:

    当然 - 首先从其中一个列表中创建 HashSet<Integer>

    Set<Integer> set = new HashSet<Integer>(l2);
    for (Integer i : l1) {
        if (set.contains(i)) {
            System.out.println("Found!");
        }
    }
    

    如果你想找到所有重复的条目,你甚至不需要编写自己的循环,因为Set&lt;E&gt; 提供了你需要的一切......

    Set<Integer> set = new HashSet<Integer>(l2);
    set.retainAll(new HashSet<Integer>(l1));
    

    之后,set 将成为两个列表的交集。

    请注意,如果您的两个列表都已开始排序,那么您的效率可能会更高。您只需同时对两者进行迭代,将“光标”向前移动到当前具有较小值的迭代器。

    【讨论】:

    • 不应该是set.contains(i)吗?
    • @dlev:是的,已修复。但是有更好的方法可以找到整个交叉点 - 请参阅我的编辑版本...
    • 非常好。以前没见过retainAll()。假设他只想要副本(而不是对每个副本都采取行动),那就更干净了。
    • @sitsOnRedChair:不,这不是 O(n^2) - 因为在 HashSet 中的查找是 O(1),而不是 O(n)。
    • @sfjac:啊,我明白你的意思了。这很容易解决,只需创建一个新集合...将编辑。
    【解决方案2】:

    通常的方法是将第一个列表中的每个项目添加到HashSet,然后测试第二个列表中的每个项目是否存在于该集合中:

    Set<Integer> firstSet = new HashSet<Integer>(l1);
    for (Integer i : l2) {
        if (firstSet.contains(i)) {
            // Do stuff
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-15
      • 2011-12-11
      • 2021-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多