Все ответы, которые я вижу здесь, O (n). Разве это не было бы лучше?:
template <class Key, class Compare, class Allocator>
std::set<Key, Compare, Allocator>
set_subtract(std::set<Key, Compare, Allocator>&& lhs,
const std::set<Key, Compare, Allocator>& rhs) {
if (lhs.empty()) { return lhs; }
// First narrow down the overlapping range:
const auto rhsbeg = rhs.lower_bound(*lhs.begin());
const auto rhsend = rhs.upper_bound(*lhs.rbegin());
for (auto i = rhsbeg; i != rhsend; ++i) {
lhs.erase(*i);
}
return std::move(lhs);
}
Кажется, это правильно. Я не уверен, как справиться со случаем, когда тип Compare
не полностью определяет его поведение, как если бы Compare
был std::function<bool(int,int)>
, но кроме этого, это, кажется, работает правильно и должно быть как O ((num перекрытие) • log (lhs.size()
)).
В случае, если lhs
не содержит *i
, возможно, возможно дальнейшую оптимизацию, выполнив O (log (rhs.size()
)) поиск следующего элемента rhs
, который> = следующий элемент lhs
. Это оптимизировало бы случаи, когда lhs = {0, 1000}
и rhs = {1, 2, ..., 999}
делали вычитание во время регистрации.