Reputation: 19071
I have 2 lists with same Object type.
List A [ foo, bar, moo, woo, pee ]
List B [ bar, woo ]
I want to compare those 2 lists and if the name matches, set its property to true.
For instance,
if(ListA[1].name.equals(ListB[0].name)) { //match name 'bar' and 'bar'
ListA[1].hasSameName = true;
}
something like that.
I can write O(N^2) solution.
for(Talent checkedTalent : ListA) {
for(Talent filteredTalent : ListB) {
if( checkedTalent.Id.equals(filteredTalent.Id) ) {
filteredTalent.isSelected = true;
}
}
}
Can this be done in more efficient way?
Upvotes: 3
Views: 3136
Reputation: 20371
Notice that the O(n2) solution has that time-complexity because for each element from ListA
, you must check all of ListB
(again). You could reduce to O(n) if you could somehow do an O(1) lookup on ListB
for the current element from ListA
. One data structure that you can use to do that is a Map
.
So, if you build a Map
out of one of the lists and traverse the other, looking up each element in the Map
to see if there is match, you can reduce the overall time complexity to O(n) - at the cost of O(n) space.
For example:
Map<String, Talent> map = new HashMap<String, Talent>();
for(Talent t : ListA)
{
// traverse each talent into
// a map element.
map.put(t.id, t);
}
for(Talent t : ListB)
{
if(map.containsKey(t.id))
{
t.isSelected = true;
}
}
Upvotes: 4
Reputation: 14479
You can create a Set from the first List:
Set mySet = new HashSet(listA);
Now you loop over listB:
for(Object foo : listB)
if(mySet.contains(foo))
foo.isSelected = true
This is O(n * lg n), I think, but I'm not going to provide a proof. :)
Upvotes: 1
Reputation: 11688
For some inspiration on how to do this more efficiently, read up on how a SQL join can be implemented, namely a Nested loop join, a Nested loop join with a b-tree index (sort one and binary search through it for each element in the other), a Merge join, or a Hash join. Same concept.
Upvotes: 1
Reputation: 54806
Use hashing for an O(n) solution (assuming an efficient hash implementation):
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;
}
}
Upvotes: 5
Reputation: 82559
Sort then (2*(n log n)) and then walk your way along each list (2*n).
Upvotes: 3