Рассмотрим двоичную кучу, содержащую n чисел (в корне хранится наибольшее число). Вам дано натуральное число k ‹ n и число x. Вы должны определить, больше ли k-й самый большой элемент кучи, чем x или нет. Ваш алгоритм должен выполняться за время O(k). Вы можете использовать O(k) дополнительной памяти
как определить, больше ли k-й самый большой элемент кучи, чем x
- -1: это интересная проблема, но это неправильный способ задать вопрос. Пожалуйста, не копируйте здесь задание дословно. 07.02.2011
Ответы:
Простые dfs могут сделать эту работу. У нас есть счетчик, установленный на ноль. Начните с корня и на каждой итерации проверяйте значение текущего узла; если он больше x, то увеличиваем счетчик и продолжаем алгоритм для одного из дочерних узлов. Алгоритм завершается, если счетчик больше, чем равно k, или если не осталось узла для проверки. Время выполнения равно O(k), потому что будет повторяться не более k узлов, а каждая итерация выполняется за O(1).
Псевдокод выглядит следующим образом.
void CheckNode(Node node,int k, int x, ref int counter)
{
if (node.value > x)
{
counter++;
if (counter >= k)
return;
CheckNode(node.Left, k, x, ref counter);
CheckNode(node.Right,k, x, ref counter);
}
}
используй это:
counter = 0;
CheckNode(root,index,val,counter );
if (counter >= index)
return true;
return false;
если node.value ‹ x, то все дочерние значения меньше x, и нет необходимости проверять.
Как упоминал @Eric Mickelsen в комментариях, время выполнения в худшем случае составляет ровно 2k-1 (k> 0) следующим образом.
Количество посещенных узлов со значениями больше x будет не более k. Каждый узел, посещенный со значением меньше x, должен быть дочерним по отношению к посещенному узлу со значением больше x. Однако, поскольку каждый посещенный узел, кроме корня, должен иметь родителя со значением больше x, количество посещенных узлов со значением меньше x должно быть не более ((k-1)*2)-(k-1) = k -1, так как k-1 из (k-1)*2 дочерних элементов имеют значения больше, чем x. Это означает, что мы посещаем k узлов больше x и k-1 меньше x, что равно 2k-1.
node.left
может быть как меньше, так и больше, чемnode.right
. Есть изображение двоичной кучи. 07.02.2011x
). Ваш алгоритм объявит 19 вторым наибольшим значением, 17 - третьим, 2 - четвертым, 7 - пятым и так далее. Но все мы знаем, что это не так. 07.02.2011x
, нет необходимости находить K-й по величине элемент, В случай, который просто меньше, чем K-й самый большой элемент, вы знаете, что все родители (на пути от корня до K-го самого большого элемента) больше этого, поэтому максимальная высота дерева до K-го самого большого элемента равнаK
, также вы просто проверяете дочерний элемент, если родитель больше, чем x (не более K раз), поэтому вы не проверяли более 3 * k узлов, пока не достигли K-го наибольшего элемента. 14.12.2011return
вcounter >=k
, а неcounter ==k
? 15.07.2014