我有两个具有相同对象类型的列表。
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;
}
}
}
这可以更有效的方式完成吗?
答案 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 join或Hash join。同样的概念。
答案 4 :(得分:1)
您可以从第一个列表中创建一个集:
Set mySet = new HashSet(listA);
现在你循环遍历listB:
for(Object foo : listB)
if(mySet.contains(foo))
foo.isSelected = true
我认为这是O(n * lg n),但我不打算提供证据。 :)