To answer your question about efficiency, there's a bit of additional information needed: How large (or small) are the arrays usually? How often do you have to check which values in Given1/2 are not contained in Input? Can you keep (sorted) copies of the arrays? If so, can you keep them synchronized (because for example Input it only appended and nothing in the middle or beginning is removed)?
If the sizes of Given1/2 are k, l and size of Input is n, then trivially checking every element against the entire input array will take k*l*n comparisons. If k and l are typically quite small that isn't so bad (you can also check k and l simultaneously, then it becomes (k+l)*n). Sorting Input alone has a complexity of n*log(n), which can be significant for big n. If you constantly have to sort it, because you can't keep a sorted copy, that alone will likely take more cycles than searching with 'brute force'.
The question of size also goes to the efficiency of std::map and the like. They are usually implemented using a form of binary tree, specifically a
red-black-tree if I recall correctly. But in order for them to be actually efficient you need lots of data (couple of hundred or thousand entries at least), otherwise the overhead of creating them isn't really worth it (they aren't much faster than simple arrays at small sizes). They do make for much better readable code though, and using them won't kill your performance compared to a manual approach. It would just most notably not be better (possibly slightly worse but nothing significant).
Now, what I'd do, if you can keep sorted copies (of all 3 arrays), is run a single loop, only incrementing the index of the array with the smallest value (or iterator, whichever you prefer). Basically like this:
Code: Select all
const_iterator inp = input.begin();
const_iterator giv1 = given1.begin();
while (inp != input.end()) {
if (giv1 != given1.end() && (*inp) == (*giv1) ) {
// same entry found
DoWhateverItIsWhenYouFoundOne();
++inp;
++giv1;
} else if (giv1 != given1.end() && (*inp) < (*giv1)) {
// Current elemenit in input was not in given
TakeElement(*inp);
++inp;
} else if (giv1 != given1.end() && (*inp) > (*giv1)) {
// Current elemenit in given was not in input
// do NOT take element, as given has to 'catch up' first, might still be in there
++giv1;
} else {
// no more elements in given (giv1 == given1.end()), take all remaining from input
TakeElement(*inp);
++inp;
}
}
You will of course need to adapt it to handle giv1 and giv2 simultaneously (possibly by just combining them into 1 array, easiest to handle)...