Вот подход, который будет работать для любого дерева (не только двоичного).Шаг предварительной обработки - выполнить Euler Tour по дереву (это всего лишь обход DFS) и создать список из этого тура.Когда вы посещаете узел в первый раз, вы добавляете его в список, а когда вы посещаете его в последний раз, вы добавляете его в список.
Пример:
x
/ \
y z
Список будетвыглядеть как: [b(x), b(y), e(y), b(z), e(z), e(x)]
.Здесь b(x)
означает ввод x
, а e(x)
означает уход x
.Теперь, когда у вас есть этот список, вы можете ответить на запрос is x an ancestor of y
, выполнив тест b(x) is before b(y) and e(y) is before e(x)
в списке.
Вопрос в том, как вы можете сделать это в постоянное время?
Для статических деревьев (что имеет место для вас), вы можете использовать таблицу поиска (он же массив) для хранения b/e
, теперь проверка занимает постоянное время.Так что это решает вашу проблему.