Я думаю, что ваша проблема может быть более сложной в анализе временной сложности, чем фактический алгоритм.
Мы знаем, что при правильном выполнении время поиска в правильно сформированном дереве AVL высотой log[2](n)
всегда будет log[2](n)
. Поиск пропущенного элемента в этом случае ничем не отличается от поиска существующего элемента.
Допустим, у вас есть дерево AVL A
, и оно включает i
и i+1
. Тогда мы знаем, что i+1
должен быть либо родительским узлом i
, а i
- левым дочерним узлом, либо i+1
- правым дочерним узлом i
. Итак, мы можем сделать вывод:
if i ^ i+1 in A => i+1(l)=i v i(r)=i+1
Таким образом, если вы найдете i
и его родительский узел не равен i+1
, то его правый дочерний узел должен быть i+1
. Вы можете расширить это значение до i=i+1
после нахождения i+1
и продолжать проверять это условие. Самое интересное в том, что есть только одно место, на которое нужно смотреть для каждого значения i+n
после i
, если вы отслеживаете узлы, через которые вы прошли.
Если вы пройдете через [i+7, i+4, i]
, вы сразу узнаете, что если A
содержит i
, то оно не может содержать i+1
. Это связано с i+1 < i+4
, но i < i+1 < i+4
.
Если вы пройдете через [i-6, i-2, i]
, вы также сразу узнаете, что если A
содержит i+1
, то оно не может содержать i+1
. Это связано с i-2 < i+1
, но i-2 < i < i+1
.
Если вам нужно было пройти через [i+7, i+3, i+1, i]
, вы нашли i
, i+1
и, поскольку i+3
не равно i+2
, вы знаете, i+2
должен быть правым дочерним узлом i+1
, поскольку он должен не быть ребенком i+3
, поскольку он меньше, но i+1
уже занял позицию левого ребенка. Таким образом, вы проверяете, является ли i+1
правый дочерний элемент i+2
, вы продолжаете проверять i+4
с i+3
, по существу, используя алгоритм:
define stack //use your favourite stack implementaion
let n = root node
let i = yourval
while n.val != i
stack.push(n)
if i > n.val
n = n.right
else //equivalent to "else if i < n.val" since loop condition ensures they are not equal
n = n.left
while !stack.empty
if stack.peek.right.val != queue.peek.val + 1
//Implies parent holds value
temp = stack.pop.val + 1
if(temp != stack.peek.val) //If the parent does not hold the next value return it
return temp;
else //Right child holds value
stack.push(queue.peek.right)
i = stack.peek.val
return i+1 //if the stack is empty eventually return the next value
Из-за того, как формируются деревья AVL, ваш стек будет не более 2*logn[2](n)
элементов большого размера (если i
- это лист на LHS, а последнее значение - это лист на RHS). Таким образом, в целом ваш поиск займет log[2](n)
для начального поиска i
и еще одного 2*log[2](n)
вместе взятых, что составляет 3*log[2](n)
, что в Большом Омикроне все еще равно O(log[2](n))
.