Я думаю, что jonderry очень близок, но родительские указатели требуют памяти \ Omega (n), то есть они существенно увеличивают использование памяти. То, что он делает, - это два скоординированных обхода в противоположных направлениях (от малого к большому и виверса), пытающихся держать сумму всегда близко к цели, и вы можете управлять этим с помощью двух стеков, и стеки могут расти только до глубины дерева и это O (log n). Я не знаю, если это «маленькая» дополнительная память, но, конечно, это меньше дополнительной памяти и o (n). Так что это точно так же, как в собственном комментарии jonderry, но штраф за время выполнения отсутствует, потому что обход бинарного дерева с использованием только стека является хорошо известной и эффективной операцией, которая, безусловно, O (n). Таким образом, у вас есть увеличивающийся итератор ii и убывающий итератор di.
x = ii.next()
y = di.next()
while (true) {
try:
if x + y > target {y = di.next()}
if x + y < target {x = ii.next()}
if x + y == target {return (x,y)}
except IterError:
break
}
return None
Я только что столкнулся с той же проблемой в контексте вычисления псевдомедиана, медианы всех попарных средних в выборке.