Scrivi il programma più breve per calcolare l'altezza di un albero binario


18

L'altezza di un albero binario è la distanza dal nodo radice al figlio nodo più lontano dalla radice.

Di seguito è riportato un esempio:

           2 <-- root: Height 1
          / \
         7   5 <-- Height 2
        / \   \
       2   6   9 <-- Height 3
          / \  /
         5  11 4 <-- Height 4 

Altezza dell'albero binario: 4

Definizione di un albero binario

Un albero è un oggetto che contiene un valore intero con segno e altri due alberi o puntatori ad essi.

La struttura della struttura ad albero binario è simile alla seguente:

typedef struct tree
{
  struct tree * l;

  struct tree * r;

  int v;

} tree;

La sfida:

Ingresso

La radice di un albero binario

Produzione

Il numero che rappresenta l'altezza di un albero binario

Supponendo che ti venga data la radice di un albero binario come input, scrivi il programma più breve che calcola l'altezza di un albero binario e restituisce l'altezza. Vince il programma con il minor numero di byte (spazi bianchi contabili).


4
Cosa prendono le lingue senza puntatori?
Jonathan Allan il

4
... ma poi il mio oggetto albero potrebbe avere solo una proprietà, diciamo h. Potrebbe essere meglio definire una struttura specifica fatta solo di liste ai fini di questa sfida.
Jonathan Allan il

11
@ T.Salim In futuro, considera di pubblicare prima nella sandbox .
wizzwizz4,

1
Quindi, una rappresentazione valida è un elenco di lunghezza 3 in [root_value, left_node, right_node]cui ciascuno left_nodee right_nodesono anche alberi binari accettabili? Sarà banale in molte lingue, ma potrebbe essere divertente in alcune altre.
Jonathan Allan il

3
Puoi modificare la domanda per includere ciò che costituisce una struttura binaria valida? Forse una definizione come a tree is an object that contains a value and either two other trees or pointers to them. Sarebbe anche piacevole una definizione che includa le lingue senza oggetti.
Jo King,

Risposte:


11

Gelatina , 3 byte

ŒḊ’

Un collegamento monadico che accetta un elenco che rappresenta l'albero:, [root_value, left_tree, right_tree]dove ciascuna di left_treee right_treesono strutture simili (vuote se necessario), che fornisce l'altezza.

Provalo online!

Come?

Abbastanza banale in Jelly:

ŒḊ’ - Link: list, as described above
ŒḊ  - depth
  ’ - decremented (since leaves are `[value, [], []]`)

Jonathon Allen, questa è una lingua interessante che stai usando. Come nuovo arrivato, potresti fornire un link o un riferimento al sito web che tutori le persone su come usare Jelly?
T. Salim,

4
Fai clic sul collegamento nell'intestazione: è una lingua per il golf sviluppata da Dennis , uno dei moderatori del sito.
Jonathan Allan il

2
Mi chiedo quanto sia controverso rappresentare una foglia come xinvece di [x, [], []]...
Erik the Outgolfer

@EriktheOutgolfer Per mantenere la natura "pointer" e "struct" della domanda, penso che ogni nodo dovrebbe avere la stessa forma.
Jonathan Allan il

10

Python 2 ,  35  33 byte

Grazie ad Arnauld per aver notato una svista e risparmiato 4.

f=lambda a:a>[]and-~max(map(f,a))

Una funzione ricorsiva che accetta un elenco che rappresenta l'albero:, [root_value, left_tree, right_tree]dove ciascuna di left_treee right_treesono strutture simili (vuote se necessario), che restituisce l'altezza.

Provalo online!

Nota che []tornerà False, ma in Python False==0.


Alla stessa persona è permesso dare due risposte diverse alla stessa domanda?
T. Salim,

6
Sì, certo, il golf è una competizione a livello linguistico. Anche una seconda voce nella stessa lingua è talvolta accettabile, se l'approccio è molto diverso.
Jonathan Allan il

@Arnauld Credo di sì (io avevo assunto non interi potrebbero essere presenti per qualche motivo)
Jonathan Allan

6

Haskell, 33 byte

h L=0 
h(N l r _)=1+max(h l)(h r)

Usando il tipo di albero personalizzato data T = L | N T T Int, che è l'equivalente di Haskell della struttura C data nella sfida.

Provalo online!


6

Perl 6 , 25 byte

{($_,{.[*;*]}...*eqv*)-2}

L'input è un elenco di 3 elementi (l, r, v). L'albero vuoto è l'elenco vuoto.

Provalo online!

Spiegazione

{                       }  # Anonymous block
    ,        ...  # Sequence constructor
  $_  # Start with input
     {.[*;*]}  # Compute next element by flattening one level
               # Sadly *[*;*] doesn't work for some reason
                *eqv*  # Until elements doesn't change
 (                   )-2  # Size of sequence minus 2

Vecchia soluzione, 30 byte

{+$_&&1+max map &?BLOCK,.[^2]}

Provalo online!


Il &?BLOCKtrucco è interessante ma è un paio di byte più corto per assegnare il blocco a $!
Jo King,

@JoKing Non lo so. Memorizzare la soluzione sfida in un volatile globale come $!o $/mi viene voglia di imbrogliare.
nwellnhof,

(Ab) usando variabili come $! e $ / è una pratica abbastanza standard per giocare a golf P6.
user0721090601

6

05AB1E , 11 7 5 byte

Δ€`}N

-4 byte grazie a @ExpiredData .
-2 byte grazie a @Grimy .

Il formato di input è simile alla risposta Jelly: un elenco che rappresenta l'albero:, [root_value, left_tree, right_tree]dove ciascuna di left_treee right_treesono strutture simili (opzionalmente vuota). Cioè [2,[7,[2,[],[]],[6,[5,[],[]],[11,[],[]]]],[5,[],[9,[4,[],[]],[]]]]rappresenta l'albero dalla descrizione della sfida.

Provalo online o verifica alcuni altri casi di test .

Spiegazione:

Δ     # Loop until the (implicit) input-list no longer changes:
  €`  #  Flatten the list one level
}N    # After the loop: push the 0-based index of the loop we just finished
      # (which is output implicitly as result)

Si noti che sebbene 05AB1E sia basato su 0, il ciclo di modifiche Δfa sì che l'indice di output sia corretto, poiché ha bisogno di un'iterazione aggiuntiva per verificare che non cambi più.



@ExpiredData Ah, certo .. Grazie! :)
Kevin Cruijssen il


@Grimy Ho pensato che usare l'indice al di fuori di un ciclo funzionasse solo nel codice legacy ..: S Grazie!
Kevin Cruijssen,

5

JavaScript (ES6),  35  33 byte

Struttura di input: [[left_node], [right_node], value]

f=([a,b])=>a?1+f(f(a)>f(b)?a:b):0

Provalo online!

Commentate

f =                       // f is a recursive function taking
([a, b]) =>               // a node of the tree split into
                          // a[] = left child, b[] = right child (the value is ignored)
  a ?                     // if a[] is defined:
    1 +                   //   increment the final result for this branch
    f(                    //   and add:
      f(a) > f(b) ? a : b //     f(a) if f(a) > f(b) or f(b) otherwise
    )                     //
  :                       // else:
    0                     //   stop recursion and return 0

Sembra che puoi salvare un byte con a&&-~.
Shaggy

1
@Shaggy Questo porterebbe a confronti con undefined .
Arnauld


4

JavaScript (Node.js) , 32 byte

f=a=>/,,/.test(a)&&f(a.flat())+1

Provalo online!

Usare il nome flatinvece di flatteno smooshè un'ottima idea per il golf del codice.

Utilizzo []per nodo null nella struttura e [left, right, value]per nodi. valueecco un numero intero.



3

Haskell, 28 byte

Utilizzando la seguente definizione di dati:

data T a = (:&) a [T a]

L'altezza è:

h(_:&x)=foldr(max.succ.h)0 x

2

Schema, 72 byte

(define(f h)(if(null? h)0(+ 1(max(f(car(cdr h)))(f(car(cdr(cdr h))))))))

Versione più leggibile:

(define (f h)
   (if (null? h)
      0
      (+ 1 
         (max
             (f (car (cdr h)))
             (f (car (cdr (cdr h))))
         )
      )
   )
)

Utilizzo degli elenchi del modulo (dati, sinistra, destra) per rappresentare un albero. Per esempio

   1
  / \
  2  3
 /\
 4 5

is represented as: (1 (2 (4 () ()) (5 () ())) (3 () ())

(1
   (2
      (4 () ())
```   (5 () ())
   (3 () ())
)

Provalo online!


2

R , 51 byte

function(L){while(is.list(L<-unlist(L,F)))T=T+1;+T}

Provalo online!

  • Input: un elenco nidificato nel formato:list(ROOT_ELEMENT, LEFT_TREE, RIGHT_TREE)

  • Algoritmo: appiattisce iterativamente l'albero di un livello fino a quando non diventa un vettore piatto: il conteggio delle iterazioni corrisponde alla profondità massima.

Ispirato da soluzione @KevinCruijssen


Alternativa ricorsiva:

R , 64 byte

`~`=function(L,d=0)'if'(is.list(L),max(L[[2]]~d+1,L[[3]]~d+1),d)

Provalo online!

Ridefinisce la funzione / operatore '~' rendendola in grado di calcolare la profondità massima di un albero memorizzato in una struttura di elenco.

La struttura dell'elenco di un albero è nel formato: list(ROOT_ELEMENT, LEFT_TREE, RIGHT_TREE)

  • -2 grazie a @Giuseppe

perché usi d=1e poi d-1alla fine? Non potresti iniziare da 0?
Giuseppe,

Inoltre sono passato >a ~ qui in modo che i casi di test siano più facili da inserire
Giuseppe

@Giuseppe: certo ... mi mancava l'ovvio 🤦‍♂️
digEmAll


1

K (ngn / k) , 4 byte

Soluzione:

#,/\

Provalo online!

Spiegazione:

Penso che potrei aver perso il punto.

Rappresentando un albero come elenco di 3 elementi (nodo principale; figlio-sinistro; figlio-destro), l'esempio può essere rappresentato come

(2;
  (7;
    (,2);
    (6;
      (,5);
      (,11)
    )
  );
  (5;
    ();
    (9;
      (,4);
      ()
    )
  )
)

o: (2;(7;(,2);(6;(,5);(,11)));(5;();(9;(,4);()))) .

Quindi la soluzione è appiattire iterativamente e contare le iterazioni:

#,/\ / the solution
   \ / iterate
 ,/  / flatten
#    / count

0

Carbone , 29 byte

⊞θ⁰⊞υθFυ«≔⊕⊟ιθFΦι∧κλ⊞υ⊞Oκθ»Iθ

Provalo online! Il collegamento è alla versione dettagliata del codice. Modifica temporaneamente l'albero durante l'elaborazione. Spiegazione:

⊞θ⁰

Spingere zero sul nodo principale.

⊞υθ

Spingere il nodo principale nell'elenco di tutti i nodi.

Fυ«

Esegui una prima ricerca dell'albero.

≔⊕⊟ιθ

Ottieni la profondità di questo nodo.

FΦι∧κλ

Scorri su qualsiasi nodo figlio.

⊞υ⊞Oκθ

Indica al nodo figlio la profondità del suo genitore e spingilo nell'elenco di tutti i nodi.

»Iθ

Una volta che tutti i nodi sono stati attraversati, stampare la profondità dell'ultimo nodo. Dato che l'attraversamento è stato il primo, questa sarà l'altezza dell'albero.


0

Stax , 5 byte

▐▌µ╡⌂

Esegui ed esegui il debug

Stax non ha né puntatori né valori null, quindi rappresento l'input like [2,[7,[2,[],[]],[6,[5,[],[]],[11,[],[]]]],[5,[],[9,[4,[],[]],[]]]]. Forse è un vantaggio ingiusto, ma era il più vicino che potessi ottenere.

Disimballato, non modificato e commentato, il codice è simile al seguente.

        The input starts on top of the input stack
Z       Tuck a zero underneath the top value in the stack.  Both values end up on the main stack.
D       Drop the first element from array
F       For each remaining element (the leaves) run the rest of the program
  G^    Recursively call the entire program, then increment
  T     Get maximum of the two numbers now ow the stack

Esegui questo


0

Kotlin, 45 byte

val Tree.h:Int get()=1+maxOf(l?.h?:0,r?.h?:0)

Supponendo che sia definita la seguente classe

class Tree(var v: Int, var l: Tree? = null, var r: Tree? = null)

Provalo online


0

Julia, 27 byte

f(t)=t≢()&&maximum(f,t.c)+1

Con la seguente struttura che rappresenta l'albero binario:

struct Tree
    c::NTuple{2,Union{Tree,Tuple{}}}
    v::Int
end

cè una tupla che rappresenta i nodi sinistro e destro e la tupla vuota ()viene utilizzata per segnalare l'assenza di un nodo.


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.