比较2个列表中的元素时如何避免O(N ^ 2)?

时间:2011-04-20 04:06:06

标签: java algorithm list

我有两个具有相同对象类型的列表。

List A [ foo, bar, moo, woo, pee ]

List B [ bar, woo ]

我想比较这两个列表,如果名称匹配, 将其属性设置为true。

例如,

if(ListA[1].name.equals(ListB[0].name)) { //match name 'bar' and 'bar'
    ListA[1].hasSameName = true;
}

类似的东西。

我可以写O(N ^ 2)解决方案。

for(Talent checkedTalent : ListA) {
    for(Talent filteredTalent : ListB) {
        if( checkedTalent.Id.equals(filteredTalent.Id) ) {
            filteredTalent.isSelected = true;   
        }
    }
}

这可以更有效的方式完成吗?

5 个答案:

答案 0 :(得分:4)

请注意,O(n 2 )解决方案具有时间复杂度,因为对于ListA中的每个元素,您必须检查{em>的所有 {{1 (再次)。如果你能以某种方式在ListB上对来自ListB的当前元素进行O(1)查找,则可以减少到O(n)。您可以使用的一种数据结构是ListA

因此,如果您从其中一个列表中构建Map并遍历另一个列表,查找Map中的每个元素以查看是否存在匹配,则可以减少总体时间复杂度到O(n) - 以O(n)空间为代价。

例如:

Map

答案 1 :(得分:4)

对O(n)解决方案使用散列(假设有效的散列实现):

Set<String> ids = new HashSet<String>(ListA.size());
for(Talent checkedTalent : ListA) {
    ids.add(checkedTalent.Id);
}
for(Talent filteredTalent : ListB) {
    if (ids.contains(filteredTalent.Id)) {
        filteredTalent.isSelected = true;
    }
}

答案 2 :(得分:3)

然后排序(2 *(n log n)),然后沿着每个列表(2 * n)走。

答案 3 :(得分:1)

有关如何更有效地完成此操作的一些灵感,请阅读有关如何实现SQL连接的信息,即Nested loop join,带有b-tree索引的嵌套循环连接(排序一和二进制搜索)对于另一个中的每个元素,它是Merge joinHash join。同样的概念。

答案 4 :(得分:1)

您可以从第一个列表中创建一个集:

Set mySet = new HashSet(listA);

现在你循环遍历listB:

for(Object foo : listB)
    if(mySet.contains(foo))
        foo.isSelected = true

我认为这是O(n * lg n),但我不打算提供证据。 :)