Viết chương trình ngắn nhất để tính chiều cao của cây nhị phân


18

Chiều cao của cây nhị phân là khoảng cách từ nút gốc đến nút con xa nhất với gốc.

Dưới đây là một ví dụ:

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

Chiều cao của cây nhị phân: 4

Định nghĩa cây nhị phân

Cây là một đối tượng chứa giá trị nguyên đã ký và hai cây khác hoặc con trỏ tới chúng.

Cấu trúc của cấu trúc cây nhị phân trông giống như sau:

typedef struct tree
{
  struct tree * l;

  struct tree * r;

  int v;

} tree;

Các thách thức:

Đầu vào

Rễ cây nhị phân

Đầu ra

Số đại diện cho chiều cao của cây nhị phân

Giả sử bạn được cung cấp gốc của cây nhị phân làm đầu vào, hãy viết chương trình ngắn nhất tính chiều cao của cây nhị phân và trả về chiều cao. Chương trình có số lượng byte (khoảng trắng kế toán) ít nhất sẽ thắng.


4
Làm gì mà ngôn ngữ không có con trỏ mất?
Jonathan Allan

4
... nhưng sau đó, đối tượng cây của tôi có thể có một tài sản, nói h. Có thể tốt hơn để xác định một cấu trúc cụ thể được tạo ra chỉ trong danh sách cho mục đích của thách thức này.
Jonathan Allan

11
@ T.Salim Trong tương lai, vui lòng xem xét việc đăng bài trong hộp cát trước.
wizzwizz4

1
Vì vậy, một đại diện hợp lệ là một danh sách có độ dài 3 [root_value, left_node, right_node]trong đó mỗi cây left_noderight_nodecũng là cây nhị phân có thể chấp nhận? Nó sẽ là tầm thường trong nhiều ngôn ngữ, nhưng có thể là niềm vui ở một số ngôn ngữ khác.
Jonathan Allan

3
Bạn có thể chỉnh sửa câu hỏi để bao gồm những gì cấu thành một cấu trúc nhị phân hợp lệ không? Có lẽ một định nghĩa như thế a tree is an object that contains a value and either two other trees or pointers to them. Một định nghĩa bao gồm các ngôn ngữ không có đối tượng cũng sẽ rất hay.
Jo King

Câu trả lời:


11

Thạch , 3 byte

ŒḊ’

Liên kết đơn âm chấp nhận một danh sách đại diện cho cây : [root_value, left_tree, right_tree], trong đó mỗi cấu trúc left_treeright_treelà các cấu trúc tương tự (trống nếu cần), mang lại chiều cao.

Hãy thử trực tuyến!

Làm sao?

Khá tầm thường trong Jelly:

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

Jonathon Allen, đó là một ngôn ngữ thú vị mà bạn đang sử dụng. Là người mới, bạn có thể cung cấp một liên kết hoặc giới thiệu trang web hướng dẫn mọi người cách sử dụng Jelly không?
T. Salim

4
Nhấp vào liên kết trong tiêu đề - đó là Ngôn ngữ chơi gôn được phát triển bởi Dennis , một trong những người điều hành trang web.
Jonathan Allan

2
Tôi tự hỏi sẽ gây tranh cãi như thế nào khi đại diện cho một chiếc lá xthay vì [x, [], []]...
Erik the Outgolfer

@EriktheOutgolfer Để giữ nguyên bản chất "con trỏ" và "cấu trúc" của câu hỏi Tôi nghĩ rằng mọi nút phải có cùng dạng.
Jonathan Allan

10

Python 2 ,  35  33 byte

Cảm ơn Arnauld vì đã không giám sát và tiết kiệm 4.

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

Hàm đệ quy chấp nhận một danh sách đại diện cho cây : [root_value, left_tree, right_tree], trong đó mỗi cấu trúc left_treeright_treelà các cấu trúc tương tự (trống nếu cần), sẽ trả về chiều cao.

Hãy thử trực tuyến!

Lưu ý rằng []sẽ trở lại False, nhưng trong Python False==0.


Cùng một người được phép đưa ra hai câu trả lời khác nhau cho cùng một câu hỏi?
T. Salim

6
Vâng, tất nhiên, golf là một cuộc thi ở cấp độ ngôn ngữ. Ngay cả một mục thứ hai trong cùng một ngôn ngữ đôi khi cũng được chấp nhận, nếu cách tiếp cận rất khác nhau.
Jonathan Allan

@Arnauld Đoán như vậy (Tôi cho rằng không có số nguyên có thể có mặt vì một số lý do)
Jonathan Allan

6

Haskell, 33 byte

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

Sử dụng loại cây tùy chỉnh data T = L | N T T Int, tương đương với Haskell của cấu trúc C được đưa ra trong thử thách.

Hãy thử trực tuyến!


6

Perl 6 , 25 byte

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

Đầu vào là danh sách 3 yếu tố (l, r, v). Cây trống là danh sách trống.

Hãy thử trực tuyến!

Giải trình

{                       }  # 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

Giải pháp cũ, 30 byte

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

Hãy thử trực tuyến!


Thủ &?BLOCKthuật này rất thú vị nhưng ngắn hơn một vài byte để gán khối cho $!
Jo King

@JoKing tôi không biết. Lưu trữ giải pháp thách thức trong một thế giới đầy biến động như $!hoặc $/cảm thấy như lừa dối tôi.
nwellnhof

(Ab) sử dụng các biến như $! và $ / là cách thực hành khá chuẩn để chơi gôn P6.
user0721090601

6

05AB1E , 11 7 5 byte

Δ€`}N

-4 byte nhờ @ExpiredData .
-2 byte nhờ @Grimy .

Định dạng đầu vào tương tự như câu trả lời Jelly: một danh sách đại diện cho cây : [root_value, left_tree, right_tree], trong đó mỗi cấu trúc left_treeright_treelà các cấu trúc tương tự (tùy chọn trống). Tức là [2,[7,[2,[],[]],[6,[5,[],[]],[11,[],[]]]],[5,[],[9,[4,[],[]],[]]]]đại diện cho cây từ mô tả thách thức.

Hãy thử trực tuyến hoặc xác minh một vài trường hợp thử nghiệm .

Giải trình:

Δ     # 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)

Lưu ý rằng mặc dù 05AB1E dựa trên 0, vòng lặp thay đổi Δlàm cho chỉ mục đầu ra là chính xác, bởi vì nó cần một lần lặp bổ sung để kiểm tra xem nó không còn thay đổi nữa.



@ExpiredData Ah, tất nhiên .. Cảm ơn! :)
Kevin Cruijssen


@Grimy Tôi nghĩ rằng việc sử dụng chỉ mục bên ngoài một vòng lặp chỉ hoạt động trong mã kế thừa ..: S Cảm ơn!
Kevin Cruijssen

5

JavaScript (ES6),  35  33 byte

Cấu trúc đầu vào: [[left_node], [right_node], value]

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

Hãy thử trực tuyến!

Đã bình luận

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

Có vẻ như bạn có thể lưu một byte với a&&-~.
Xù xì

1
@Shaggy Điều đó sẽ dẫn đến sự so sánh với không xác định .
Arnauld

4

C, 43 byte

h(T*r){r=r?1+(int)fmax(h(r->l),h(r->r)):0;}

Cấu trúc của cây nhị phân như sau:

typedef struct tree
{
  struct tree * l;

  struct tree * r;

  int v;

} tree;

2
55 byte Hãy thử trực tuyến! Một số thủ thuật chơi gôn dành riêng cho C có ở đây!
ErikF

1
@ErikF Hoặc 45 byte
Arnauld


3
Nếu bài gửi của bạn dựa trên cờ, bạn có thể vui lòng thêm chúng vào tiêu đề của bài gửi của mình không?
Jo King

1
Xây dựng trên @nwellnhof 42 byte
ceilingcat

4

JavaScript (Node.js) , 32 byte

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

Hãy thử trực tuyến!

Sử dụng tên flatthay vì flattenhoặc smooshlà một ý tưởng tuyệt vời cho mã golf.

Sử dụng []cho nút null trong cây và [left, right, value]cho các nút. valueđây là một số nguyên.



3

Haskell, 28 byte

Sử dụng định nghĩa dữ liệu sau:

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

Chiều cao là:

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

2

Lược đồ, 72 byte

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

Phiên bản dễ đọc hơn:

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

Sử dụng danh sách biểu mẫu (dữ liệu, trái, phải) để thể hiện một cây. Ví dụ

   1
  / \
  2  3
 /\
 4 5

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

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

Hãy thử trực tuyến!


2

R , 51 byte

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

Hãy thử trực tuyến!

  • Đầu vào: một danh sách lồng nhau trong định dạng:list(ROOT_ELEMENT, LEFT_TREE, RIGHT_TREE)

  • Thuật toán: Lặp đi lặp lại làm phẳng cây theo một cấp độ cho đến khi nó trở thành một vectơ phẳng: số lần lặp tương ứng với độ sâu tối đa.

Lấy cảm hứng từ giải pháp @KevinCruijssen


Thay thế đệ quy:

R , 64 byte

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

Hãy thử trực tuyến!

Xác định lại hàm / toán tử '~'làm cho nó có thể tính toán độ sâu tối đa của cây được lưu trữ trong cấu trúc danh sách.

Cấu trúc danh sách của cây có định dạng: list(ROOT_ELEMENT, LEFT_TREE, RIGHT_TREE)

  • -2 cảm ơn @Giuseppe

Tại sao bạn sử dụng d=1và sau đó d-1ở cuối? Bạn không thể bắt đầu lúc 0?
Giuseppe

Ngoài ra tôi chuyển >đến ~ đây vì vậy các trường hợp thử nghiệm được dễ dàng hơn để nhập
Giuseppe

@Giuseppe: tất nhiên ... tôi đã bỏ lỡ điều rõ ràng 🤦‍♂️
digEmAll


1

K (ngn / k) , 4 byte

Giải pháp:

#,/\

Hãy thử trực tuyến!

Giải trình:

Tôi nghĩ rằng tôi có thể đã bỏ lỡ điểm.

Đại diện cho một cây dưới dạng danh sách 3 mục (nút cha; con trái; con phải), ví dụ có thể được biểu diễn dưới dạng

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

hoặc : (2;(7;(,2);(6;(,5);(,11)));(5;();(9;(,4);()))).

Vì vậy, giải pháp là lặp đi lặp lại và đếm số lần lặp:

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

0

Than , 29 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Tạm thời sửa đổi cây trong quá trình xử lý. Giải trình:

⊞θ⁰

Đẩy số 0 vào nút gốc.

⊞υθ

Đẩy nút gốc vào danh sách tất cả các nút.

Fυ«

Thực hiện tìm kiếm đầu tiên của cây.

≔⊕⊟ιθ

Lấy độ sâu của nút này.

FΦι∧κλ

Vòng lặp trên bất kỳ nút con.

⊞υ⊞Oκθ

Nói cho nút con độ sâu của cha mẹ và đẩy nó vào danh sách tất cả các nút.

»Iθ

Khi tất cả các nút đã được duyệt qua, hãy in độ sâu của nút cuối cùng. Vì đường ngang là chiều rộng đầu tiên, đây sẽ là chiều cao của cây.


0

Stax , 5 byte

▐▌µ╡⌂

Chạy và gỡ lỗi nó

Stax không có con trỏ cũng không có giá trị null, vì vậy tôi đại diện cho đầu vào như [2,[7,[2,[],[]],[6,[5,[],[]],[11,[],[]]]],[5,[],[9,[4,[],[]],[]]]] . Có lẽ đó là một lợi thế không công bằng, nhưng đó là lần gần nhất tôi có thể có được.

Giải nén, không ghi chú và nhận xét, mã trông như thế này.

        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

Chạy cái này


0

Kotlin, 45 byte

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

Giả sử lớp sau được định nghĩa

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

Dùng thử trực tuyến


0

Julia, 27 byte

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

Với cấu trúc sau đại diện cho cây nhị phân:

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

clà một tuple đại diện cho các nút trái và phải và tuple trống ()được sử dụng để báo hiệu sự vắng mặt của một nút.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.