Це макс-купа?


14

Купи , також відомі як пріоритетна чергу, це абстрактний тип даних. Концептуально це двійкове дерево, де діти кожного вузла менші або рівні самій вузлу. (Якщо припустити, що це макс-купа.) Коли елемент висувається або вискакується, купа переставляє себе, щоб найбільшим елементом був наступний, який повинен вискочити. Він може бути легко реалізований у вигляді дерева або як масив.

Якщо ви вирішите її прийняти, ваше завдання полягає в тому, щоб визначити, чи масив є дійсною купою. Масив складається в купі, якщо діти кожного елемента менші або рівні самій елементу. Візьмемо такий приклад:

[90, 15, 10, 7, 12, 2]

Дійсно, це двійкове дерево, розташоване у вигляді масиву. Це тому, що кожен елемент має дітей. У 90 є двоє дітей, 15 та 10 років.

       15, 10,
[(90),         7, 12, 2]

15 також мають дітей 7 та 12 років:

               7, 12,
[90, (15), 10,        2]

10 дітей:

                      2
[90, 15, (10), 7, 12,  ]

і наступним елементом також буде дитина 10 років, за винятком того, що немає місця. 7, 12 і 2 також мали б дітей, якби масив був досить довгим. Ось ще один приклад купи:

[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]

Ось візуалізація дерева, який робить попередній масив:

введіть тут опис зображення

На випадок, якщо це недостатньо зрозуміло, ось чітка формула, щоб дітям i-го елемента

//0-indexing:
child1 = (i * 2) + 1
child2 = (i * 2) + 2

//1-indexing:
child1 = (i * 2)
child2 = (i * 2) + 1

Ви повинні взяти не порожній масив як вхідний і вивести триєдне значення, якщо масив знаходиться в наборі, а помилкове значення - в іншому випадку. Це може бути 0-індексована купа або 1-індексована купа, поки ви вкажете, який формат очікує ваша програма / функція. Ви можете припустити, що всі масиви будуть містити лише додатні цілі числа. Ви не можете використовувати будь-які вбудовані купи. Це включає, але не обмежується цим

  • Функції, які визначають, чи є масив у heap-формі
  • Функції, які перетворюють масив у купу або у форму heap
  • Функції, які приймають масив як вхідні дані і повертають структуру даних купи

Ви можете використовувати цей скрипт python, щоб перевірити, чи масив знаходиться у купі-формі чи ні (0 індексовано):

def is_heap(l):
    for head in range(0, len(l)):
        c1, c2 = head * 2 + 1, head * 2 + 2
        if c1 < len(l) and l[head] < l[c1]:
            return False
        if c2 < len(l) and l[head] < l[c2]:
            return False

    return True

Тест IO:

Усі ці входи повинні повернути True:

[90, 15, 10, 7, 12, 2]
[93, 15, 87, 7, 15, 5]
[16, 14, 10, 8, 7, 9, 3, 2, 4, 1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[100, 19, 36, 17, 3, 25, 1, 2, 7]
[5, 5, 5, 5, 5, 5, 5, 5]

І всі ці входи повинні повертати помилкові:

[4, 5, 5, 5, 5, 5, 5, 5]
[90, 15, 10, 7, 12, 11]
[1, 2, 3, 4, 5]
[4, 8, 15, 16, 23, 42]
[2, 1, 3]

Як завжди, це код-гольф, тому застосовуються стандартні лазівки і найкоротша відповідь у байтах виграє!



Чи правильно, що якщо є повторювані елементи, можливо сформувати купу відповідно до цього визначення?
feersum

@feersum Про що [3, 2, 1, 1]?
Ніл

@feersum Це чудовий момент, я про це не думав. Я оновив опис купи і додав приклад із дублюючими елементами. Дякую!
Джеймс

5
Купа також не відома як черга пріоритетів. Пріоритетною чергою є абстрактний тип даних. Купа - це структура даних, яка іноді використовується для реалізації черги пріоритету (сама купа реалізована на основі ще більшої структури даних про фінанси, але це знаходиться поруч). Черги з пріоритетом можна реалізовувати над іншими структурами даних - як пов'язані списки.
Ліндон Уайт

Відповіді:


7

Желе, 11 9 5 байт

x2:ḊṂ

4 байти видалено завдяки Деннісу!

Спробуйте тут.

Пояснення

x2          Duplicate each element.
:Ḋ          Each element divided by the input with the first element removed,
            as integer, so there is a 0 only if some element in the duplicated
            list is less than the corresponding element in the other.
            There are also elements left unchanged, but it doesn't matter as
            the input is all positive.
Ṃ           Minimum in the list.

10

JavaScript (ES6), 34 30 байт

a=>!a.some((e,i)=>e>a[i-1>>1])

Редагувати: виправлення мого коду для уточнення специфікації коштувало 1 байт, тому дякую @ edc65 за економію 4 байт.


Він виходить з ладу з [93, 15, 87, 7, 15, 5][5, 5, 5, 5, 5, 5, 5, 5]
тестовими випробуваннями

Це працює краще і на 3 a=>!a.some((e,i)=>e>a[i-1>>1])
рази

1
@ edc65 Ці тестові скриньки були додані після того, як я написав свою відповідь.
Ніл


4

J, 24 байти

*/@:<:]{~0}:@,<.@-:@i.@#

Пояснення

*/@:<:]{~0}:@,<.@-:@i.@#  Input: s
                       #  Count of s
                    i.@   Create range [0, 1, ..., len(s)-1]
                 -:@      Halve each
              <.@         Floor each
         0   ,            Prepend a zero to it
          }:@             Remove the last value to get the parent indices of each
      ]                   Identity function to get s
       {~                 Take the values from s at the parent indices
    <:                    For each, 1 if it is less than or equal to its parent else 0
*/@:                      Reduce using multiplication and return

3

MATL , 13 12 байт

ttf2/k)>~4L)

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Масив є правдоподібним, якщо він не порожній і всі його записи ненульові. Інакше це хибність. Ось кілька прикладів .

Пояснення

t     % Take input implicitly. Duplicate
tf    % Duplicate and push indices of nonzero entries. This gives [1 2 ... n] where n
      % is input size
2/k   % Divide by 2 and round down
)     % Index into input. Gives array of parents, except for the first entry
>~    % True for entries of the input that don't exceed those in the array of parents
4L)   % Discard first entry

2

Python 2, 45 байт

f=lambda l:l==[]or l[len(l)/2-1]/l.pop()*f(l)

Виходи 0 для Falsy, ненульовий для Truthy.

Перевіряє, що останній елемент менший або рівний його батьківському індексу len(l)/2-1. Потім повторюється, щоб перевірити, чи те ж саме, що і в останньому елементі списку видалено, і так далі, поки список не буде порожнім.


48 байт:

f=lambda l,i=1:l==l[:i]or l[~-i/2]/l[i]*f(l,i+1)

Перевіряє, що в кожному індексі iелемент є не більше свого батьківського в індексі(i-1)/2 . Підрозділ підлоги дає 0, якщо це не так.

Виконання базового корпусу i/len(l)orдорівнює однаковій довжині. Я спробував блискавку спочатку, але отримав довший код (57 байт).

lambda l:all(map(lambda a,b,c:b<=a>=c,l,l[1::2],l[2::2]))

1

R, 97 88 82 байт

Сподіваюся, я правильно це зрозумів. Тепер, щоб побачити, чи можу я позбутися ще кількох байтів. Витягнув rbind і вклав у саппл і правильно поводився з 1-базисним вектором.

Реалізується як неназвана функція

function(Y)all(sapply(1:length(Y),function(X)Y[X]>=Y[X*2]&Y[X]>=Y[X*2+1]),na.rm=T)

З кількома тестовими випадками

> f=
+ function(Y)all(sapply(1:length(Y),function(X)Y[X]>=Y[X*2]&Y[X]>=Y[X*2+1]),na.rm=T)
> f(c(90, 15, 10, 7, 12, 2))
[1] TRUE
> f(c(93, 15, 87, 7, 15, 5))
[1] TRUE
> f(c(10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
[1] TRUE
> f(c(5, 5, 5, 5, 5, 5, 5, 5))
[1] TRUE
> f(c(4, 5, 5, 5, 5, 5, 5, 5))
[1] FALSE
> f(c(90, 15, 10, 7, 12, 11))
[1] FALSE
> f(c(4, 8, 15, 16, 23, 42))
[1] FALSE

Ви можете використовувати seq(Y)замість 1:length(Y).
rturnbull




0

C ++ 14, 134 105 байт

#define M(d) (2*i+d<c.size()&&(c[i]<c[2*i+d]||f(c,2*i+d)==0))
int f(auto&c,int i=0){return!(M(1)||M(2));}

Потрібно cбути контейнером, що підтримує .operator[](int)і .size(), як std::vector<int>.

Безголівки:

int f(auto& c, int i=0) {
    if (2*i+1<c.size() && c[i] < c[2*i+1]) return 0;
    if (2*i+2<c.size() && c[i] < c[2*i+2]) return 0;
    if (2*i+1<c.size() && (f(c,2*i+1) == 0)) return 0;
    if (2*i+2<c.size() && (f(c,2*i+2) == 0)) return 0;
    return 1;
}

Може бути меншим, якщо буде дозволено truthy = 0і falsy = 1.


0

R, 72 байти

Дещо інший підхід з іншим R відповіді .

x=scan();all(diff(x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)],l=N*2)<1,na.rm=T)

Читає дані зі stdin, створює вектор усіх пар порівняння, віднімає їх одна від одної та перевіряє, чи є результат від'ємним числом або нулем.

Пояснення

Прочитати вхід із stdin:

x=scan();

Створіть наші пари. Ми створюємо показники 1...N(де Nдовжина x) для батьківських вузлів. Ми приймаємо це вдвічі, оскільки кожен батько має (максимум) двох дітей. Ми також беремо дітей, (1...N)*2і (1...N)*2+1. Для індексів, що перевищують довжину x, R повертається NA"недоступно". Для введення 90 15 10 7 12 2цей код дає нам 90 15 10 7 12 2 90 15 10 7 12 2 15 7 2 NA NA NA 10 12 NA NA NA NA.

                  x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)]

У цьому векторі пар кожен елемент має свого партнера на відстані N*2. Наприклад, партнер пункту 1 розташований у позиції 12 (6 * 2). Ми використовуємо diffдля обчислення різниці між цими парами, вказуючи, lag=N*2щоб порівняти предмети з їх правильними партнерами. Будь-які операції з NAелементами просто повертаються NA.

             diff(x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)],l=N*2)

Нарешті, ми перевіряємо, що всі ці повернуті значення менші 1(тобто, що перше число, батьківське, було більше, ніж друге число, дочірнє), виключаючи NAзначення з врахування.

         all(diff(x[c(a<-1:(N<-sum(1|x)),a,a*2,a*2+1)],l=N*2)<1,na.rm=T)

0

Власне , 16 байт

Ця відповідь багато в чому ґрунтується на відповіді Jelmy на відповідь jimmy23013 . Пропозиції з гольфу вітаються! Спробуйте в Інтернеті!

;;2╟┬Σ1(tZ`i<`Mm

Ungolfing

         Implicit input a.
;;       Duplicate a twice.
2╟       Wrap two of the duplicates into a list.
┬        Transpose the duplicates.
Σ        Sum all of the columns to get a flat list like this:
           [a_0, a_0, a_1, a_1, ..., a_n, a_n]
         This gets the parent nodes of the heap.
1(t      Get a[1:] using the remaining duplicate of a.
         This is a list of the child nodes of the heap.
Z`i<`M   Check if every child node is less than its parent node.
m        Get the minimum. This returns 1 if a is a max-heap, else 0.
         Implicit return.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.