È un heap massimo?


14

Un heap , noto anche come coda di priorità, è un tipo di dati astratto. Concettualmente, è un albero binario in cui i figli di ogni nodo sono più piccoli o uguali al nodo stesso. (Supponendo che sia un max-heap.) Quando un elemento viene spinto o scoppiato, l'heap si riorganizza in modo che l'elemento più grande sia il prossimo ad essere spuntato. Può essere facilmente implementato come albero o come matrice.

La tua sfida, se scegli di accettarla, è determinare se un array è un heap valido. Un array è in forma heap se i figli di ogni elemento sono più piccoli o uguali all'elemento stesso. Prendi il seguente array come esempio:

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

Davvero, questo è un albero binario organizzato sotto forma di un array. Questo perché ogni elemento ha figli. 90 ha due figli, 15 e 10.

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

15 ha anche figli, 7 e 12:

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

10 ha figli:

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

e l'elemento successivo sarebbe anche un figlio di 10, tranne per il fatto che non c'è spazio. 7, 12 e 2 avrebbero anche dei figli se l'array fosse abbastanza lungo. Ecco un altro esempio di heap:

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

Ed ecco una visualizzazione dell'albero che l'array precedente fa:

inserisci qui la descrizione dell'immagine

Nel caso in cui questo non sia abbastanza chiaro, ecco la formula esplicita per ottenere i figli dell'i-esimo elemento

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

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

È necessario prendere una matrice non vuota come input e generare un valore di verità se la matrice è in ordine di heap e un valore di falsa in caso contrario. Può trattarsi di un heap con indicizzazione 0 o di un heap con indicizzazione 1 purché specifichi il formato previsto dal programma / funzione. Si può presumere che tutti gli array conterranno solo numeri interi positivi. Si può non usare alcun heap-comandi incorporati. Questo include, ma non è limitato a

  • Funzioni che determinano se un array è in formato heap
  • Funzioni che convertono un array in un heap o in un heap-form
  • Funzioni che accettano un array come input e restituiscono una struttura di dati heap

È possibile utilizzare questo script Python per verificare se un array è in formato heap o meno (0 indicizzato):

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

Test IO:

Tutti questi input dovrebbero restituire 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]

E tutti questi input dovrebbero restituire False:

[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]

Come al solito, si tratta di code-golf, quindi si applicano scappatoie standard e vince la risposta più breve in byte!



È corretto che se ci sono elementi ripetuti, potrebbe essere impossibile formare un mucchio secondo questa definizione?
febbraio

@feersum Che dire [3, 2, 1, 1]?
Neil,

@feersum Questo è un ottimo punto, non ci avevo pensato. Ho aggiornato la descrizione di un heap e ho aggiunto alcuni esempi con elementi duplicati. Grazie!
James,

5
Un heap non è anche noto come coda di priorità. Una coda prioritaria è un tipo di dati astratto. Un heap è una struttura di dati a volte utilizzata per implementare una coda di priorità (l'heap stesso è implementato in aggiunta a strutture di dati ancora più finanziate, ma non è questo il punto). Le code prioritarie possono essere implementate su altre strutture di dati, come gli elenchi collegati.
Lyndon White,

Risposte:


7

Gelatina, 11 9 5 byte

x2:ḊṂ

4 byte rimossi grazie a Dennis!

Provalo qui.

Spiegazione

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 byte

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

Modifica: la correzione del mio codice per il chiarimento delle specifiche costa 1 byte, quindi grazie a @ edc65 per il salvataggio di 4 byte.


Non riesce testcase 2 [93, 15, 87, 7, 15, 5]e 6[5, 5, 5, 5, 5, 5, 5, 5]
edc65

Funziona meglio ed è più corto di 3 caratteria=>!a.some((e,i)=>e>a[i-1>>1])
edc65 l'

1
@ edc65 Quelle prove sono state aggiunte dopo che ho scritto la mia risposta.
Neil,

5

Haskell, 33 byte

f(a:b)=and$zipWith(<=)b$a:b<*"xx"

o

and.(zipWith(<=).tail<*>(<*"xx"))

4

J, 24 byte

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

Spiegazione

*/@:<:]{~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 byte

ttf2/k)>~4L)

Provalo online! O verifica tutti i casi di test .

Un array è vero se non è vuoto e tutte le sue voci sono diverse da zero. Altrimenti è falso. Ecco alcuni esempi .

Spiegazione

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 byte

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

Output 0 per Falsy, diverso da zero per Truthy.

Verifica che l'ultimo elemento sia inferiore o uguale al suo genitore nell'indice len(l)/2-1. Quindi, recluta per verificare che lo stesso sia True con l'ultimo elemento dell'elenco rimosso, e così via fino a quando l'elenco è vuoto.


48 byte:

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

Verifica che in ciascun indice i, l'elemento sia al massimo relativo all'indice(i-1)/2 . La divisione piano produce 0 se non è così.

Fare il caso base i/len(l)ordà la stessa lunghezza. Inizialmente avevo provato a zippare, ma ho ottenuto un codice più lungo (57 byte).

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

1

R, 97 88 82 byte

Spero di averlo capito bene. Ora per vedere se riesco a liberarmi di qualche byte in più. Ha abbandonato la rbind e ha inserito uno sapply e ha gestito correttamente il vettore basato su 1.

Implementato come una funzione senza nome

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

Con alcuni dei casi di test

> 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

Puoi usare seq(Y)invece di 1:length(Y).
rturnbull,


1

Pyth, 8 byte

.AgV.i+h

       hQ      first element of input
      +  Q     plus input
    .i    Q    interleaved with input
  gV       Q   vectorized greater-than-or-equal comparison with input
.A             check if all results are true

Provalo online


1

Retina , 51 byte

\d+
$*
^(?!(1+ )*(1+) 1* ?(?<-1>1+ )*(?(1)(?!))1\2)

Provalo online!


Accetta un elenco di numeri separato da spazi come input. Uscite 1/ 0per verità / falso


0

C ++ 14, 134 105 byte

#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));}

Richiede cdi essere un contenitore di supporto .operator[](int)e .size(), come std::vector<int>.

Ungolfed:

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;
}

Potrebbe essere più piccolo se la verità = 0e la falsità = 1sarebbero consentite.


0

R, 72 byte

Un approccio leggermente diversa da l'altra risposta 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)

Legge l'input dallo stdin, crea un vettore di tutte le coppie di confronto, le sottrae le une dalle altre e verifica che il risultato sia un numero negativo o zero.

Spiegazione

Leggi input da stdin:

x=scan();

Crea le nostre coppie. Creiamo indici di 1...N(dove Nè la lunghezza di x) per i nodi principali. Lo prendiamo due volte poiché ogni genitore ha (al massimo) due figli. Prendiamo anche i bambini (1...N)*2e (1...N)*2+1. Per indici oltre la lunghezza di x, R restituisce NA"non disponibile". Per input 90 15 10 7 12 2, questo codice ci dà 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)]

In questo vettore di coppie, ogni elemento ha il suo partner a distanza di N*2distanza. Ad esempio, il partner dell'articolo 1 si trova nella posizione 12 (6 * 2). Usiamo diffper calcolare la differenza tra queste coppie, specificando lag=N*2di confrontare gli articoli con i loro partner corretti. Qualsiasi operazione sugli NAelementi semplicemente ritorna NA.

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

Infine, controlliamo che tutti questi valori restituiti siano inferiori a 1(ovvero che il primo numero, il genitore, fosse maggiore del secondo numero, il figlio), escludendo i NAvalori dalla considerazione.

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

0

In realtà , 16 byte

Questa risposta si basa in gran parte sulla risposta Jelly di jimmy23013 . Suggerimenti di golf benvenuti! Provalo online!

;;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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.