ค้นหาโหนดที่ลึกที่สุดของต้นไม้ไบนารี


9

เขียนโปรแกรมที่รับต้นไม้ไบนารีเป็นอินพุทและเอาท์พุทโหนดที่ลึกที่สุดและความลึกของมัน หากมีเน็คไทให้พิมพ์ปมที่เกี่ยวข้องทั้งหมดรวมถึงความลึก แต่ละโหนดจะแสดงเป็น:

T(x,x)

T(x)

T

โดยที่Tเป็นตัวระบุของตัวอักษรและตัวเลขอย่างน้อยหนึ่งตัวและแต่ละตัวxเป็นโหนดอื่น

นี่คือคำจำกัดความง่ายๆของต้นไม้ไบนารี:

  • ที่หัวของต้นไม้ไบนารีเป็นโหนด
  • โหนดในต้นไม้ไบนารีมีลูกสองคนมากที่สุด

ยกตัวอย่างเช่นการป้อนข้อมูลA(B(C,D(E)))(ด้านล่าง) 3:Eจะเอาท์พุท

ต้นที่ 1

ในขณะที่ต้นไม้ต่อไปนี้มีการผูกสามทางระหว่าง 5, 11, และ 4 และความลึกของมันคือ 3 (เริ่มจาก 0):

การป้อนข้อมูล2(7(2,6(5,11)),5(9(4)))(ด้านล่าง) 3:5,11,4จะเอาท์พุท

ต้นที่ 2

นี่คือรหัสกอล์ฟดังนั้นโค้ดที่สั้นที่สุดที่วัดเป็นไบต์จะชนะ


@ close-voter: คุณไม่แน่ใจเกี่ยวกับอะไร
Jwosty

3
บางทีความจริงที่ว่าไม่มีข้อกำหนดอินพุตหรือเอาต์พุตหรือกรณีทดสอบสำหรับอินพุตและเอาต์พุตเหล่านั้น
Doorknob

กำลังพยายามแก้ไข แต่โทรศัพท์ของฉันแย่ ... : P มันดีกว่าดังนั้น
Jwosty

3
ต้นไม้ต้นแรกไม่ควรเป็น A (B (C, D (E))?
bakerg

1
@bakerg ถูกต้องความผิดพลาดของฉัน แก้ไขแล้ว.
Jwosty

คำตอบ:


6

CJam, 49 47

0q')/{'(/):U;,+:TW>{T:W];}*TW={U]',*}*T(}/;W':@

 

0                 " Push 0 ";
q                 " Read the whole input ";
')/               " Split the input by ')' ";
{                 " For each item ";
  '(/             " Split by '(' ";
  )               " Extract the last item of the array ";
  :U;             " Assign the result to U, and discard it ";
  ,               " Get the array length ";
  +               " Add the top two items of the stack, which are the array length and the number initialized to 0 ";
  :T              " Assign the result to T ";
  W>{             " If T>W, while W is always initialized to -1 ";
    T:W];         " Set T to W, and empty the stack ";
  }*
  TW={            " If T==W ";
    U]',*         " Push U and add a ',' between everything in the stack, if there were more than one ";
  }*
  T(              " Push T and decrease by one ";
}/
;                 " Discard the top item, which should be now -1 ";
W                 " Push W ";
':                " Push ':' ";
@                 " Rotate the 3rd item to the top ";

ฉันได้ทำการปรับเปลี่ยนรูปแบบผลลัพธ์เล็กน้อยเพื่อให้สอดคล้องและคลุมเครือน้อยลง แต่ไม่ควรเกินความไม่สะดวก
Jwosty

@Jwosty ไม่ควรถ้านี่ไม่ใช่ code-golf
jimmy23013

นี่คือ code-golf ... แต่อย่างไรก็ตาม, การส่งที่ดี :)
Jwosty

คุณช่วยอธิบายวิธีการทำงานของมันได้มั้ย
Jerry Jeremiah

@JerryJeremiah แก้ไขแล้ว
jimmy23013

5

Haskell, 186 ไบต์

p@(n,s)%(c:z)=maybe((n,s++[c])%z)(\i->p:(n+i,"")%z)$lookup c$zip"),("[-1..1];p%_=[p]
(n,w)&(i,s)|i>n=(i,show i++':':s)|i==n=(n,w++',':s);p&_=p
main=interact$snd.foldl(&)(0,"").((0,"")%)

โปรแกรมเต็มรูปแบบใช้เวลาเปิดต้นไม้stdinสร้างรูปแบบเอาต์พุต spec'd บนstdout:

& echo '2(7(2,6(5,11)),5(9(4)))' | runhaskell 32557-Deepest.hs 
3:5,11,4

& echo 'A(B(C,D(E)))' | runhaskell 32557-Deepest.hs 
3:E

คำแนะนำเกี่ยวกับรหัส golf'd (เพิ่มชื่อที่ดีกว่าพิมพ์ลายเซ็นความคิดเห็นและนิพจน์ย่อยบางอันถูกดึงออกมาและตั้งชื่อ - แต่มิฉะนั้นรหัสเดียวกันรุ่น ungolf'd จะไม่ยุบรวมกันเป็นโหนดด้วยหมายเลขหรือค้นหาที่ลึกที่สุด ด้วยการจัดรูปแบบผลลัพธ์) :

type Label = String         -- the label on a node
type Node = (Int, Label)    -- the depth of a node, and its label

-- | Break a string into nodes, counting the depth as we go
number :: Node -> String -> [Node]
number node@(n, label) (c:cs) =
    maybe addCharToNode startNewNode $ lookup c adjustTable
  where
    addCharToNode = number (n, label ++ [c]) cs
        -- ^ append current character onto label, and keep numbering rest

    startNewNode adjust = node : number (n + adjust, "") cs
        -- ^ return current node, and the number the rest, adjusting the depth

    adjustTable = zip "),(" [-1..1]
        -- ^ map characters that end node labels onto depth adjustments
        -- Equivalent to [ (')',-1), (',',0), ('(',1) ]

number node _ = [node]      -- default case when there is no more input

-- | Accumulate into the set of deepest nodes, building the formatted output
deepest :: (Int, String) -> Node -> (Int, String)
deepest (m, output) (n, label)
    | n > m     = (n, show n ++ ':' : label)    -- n is deeper tham what we have
    | n == m    = (m, output ++ ',' : label)    -- n is as deep, so add on label
deepest best _ = best                           -- otherwise, not as deep

main' :: IO ()
main' = interact $ getOutput . findDeepest . numberNodes
  where
    numberNodes :: String -> [Node]
    numberNodes = number (0, "")

    findDeepest :: [Node] -> (Int, String)
    findDeepest = foldl deepest (0, "")

    getOutput :: (Int, String) -> String
    getOutput = snd

1
รหัสนั้นทำให้ฉันตกใจ
seequ

เพิ่มรหัสอธิบายแล้ว! ให้ความกลัวทำให้คุณแข็งแกร่งขึ้น !!
MtnViewMark

คุณสมควรได้รับ +1 สำหรับสิ่งนั้น
Seequ

โอ้พระเจ้าของฉันและฉันกำลังต่อสู้กับรายการ: P
Artur Trapp

4

GolfScript (75 ตัวอักษร)

ไม่ได้แข่งขันโดยเฉพาะ แต่บิดพอสมควรว่ามีความสนใจ:

{.48<{"'^"\39}*}%','-)](+0.{;.@.@>-\}:^;@:Z~{2$2$={@@.}*;}:^;Z~\-])':'@','*

รหัสมีสามขั้นตอน ก่อนอื่นเราประมวลผลสตริงอินพุตล่วงหน้า:

# In regex terms, this is s/([ -\/])/'^\1'/g
{.48<{"'^"\39}*}%
# Remove all commas
','-
# Rotate the ' which was added after the closing ) to the start
)](+

เราได้เปลี่ยนเช่นการA(B(C,D(E))) 'A'^('B'^('C'^'D'^('E'^)''^)''^)หากเรากำหนดบล็อกที่เหมาะสมให้กับ^เราสามารถทำการประมวลผลที่มีประโยชน์โดยใช้~เพื่อประเมินสตริง

ประการที่สองเราพบความลึกสูงสุด:

0.
# The block we assign to ^ assumes that the stack is
#   max-depth current-depth string
# It discards the string and updates max-depth
{;.@.@>-\}:^;
@:Z~

ในที่สุดเราเลือกโหนดที่ลึกที่สุดและสร้างผลลัพธ์:

# The block we assign to ^ assumes that the stack is
#   max-depth current-depth string
# If max-depth == current-depth it pushes the string under them on the stack
# Otherwise it discards the string
{2$2$={@@.}*;}:^;
# Eval
Z~
# The stack now contains
#   value1 ... valuen max-depth 0
# Get a positive value for the depth, collect everything into an array, and pop the depth
\-])
# Final rearranging for the desired output
':'@','*

1

Perl 5 - 85

โปรดแก้ไขโพสต์นี้เพื่อแก้ไขจำนวนตัวละคร ผมใช้sayคุณลักษณะ use 5.010;แต่ผมไม่ทราบเกี่ยวกับธงที่จะทำให้มันทำงานอย่างถูกต้องโดยไม่ต้องประกาศ

$_=$t=<>,$i=0;$t=$_,$i++while s/\w+(\((?R)(,(?R))?\))?/$1/g,/\w/;@x=$t=~/\w+/gs;say"$i:@x"

การสาธิตเกี่ยวกับ ideone

เอาต์พุตถูกคั่นด้วยช่องว่างแทนที่จะคั่นด้วยเครื่องหมายจุลภาค

รหัสนั้นใช้ regex แบบเรียกซ้ำเพื่อลบรากของต้นไม้ในป่าจนกว่าจะไม่สามารถทำได้ จากนั้นสตริงก่อนหน้าสุดท้ายจะมีโหนดใบไม้ทั้งหมดที่ระดับลึกที่สุด

ตัวอย่างการวิ่ง

2
0:2

2(3(4(5)),6(7))
3:5

2(7(2,6(5,11)),5(9(4)))
3:5 11 4

1(2(3(4,5),6(7,8)),9(10(11,12),13(14,15)))
3:4 5 7 8 11 12 14 15

1

VB.net

Function FindDeepest(t$) As String
  Dim f As New List(Of String)
  Dim m = 0
  Dim d = 0
  Dim x = ""
  For Each c In t
    Select Case c
      Case ","
        If d = m Then f.Add(x)
        x = ""
      Case "("
        d += 1
        If d > m Then f.Clear() :
        m = d
        x = ""
      Case ")"
        If d = m Then f.Add(x) : x = ""
        d -= 1
      Case Else
        x += c
    End Select
  Next
  Return m & ":" & String.Join(",", f)
End Function

อัสสัมชั: ค่าโหนดไม่สามารถมี,, (,)


1
นี่ดูเหมือนจะไม่ได้เล่นกอล์ฟเลย คุณไม่สามารถลบช่องว่างส่วนใหญ่นั้นออก (ฉันไม่รู้ VB)
seequ

ขึ้นอยู่กับพื้นที่ว่างบางส่วนเป็นสำคัญ
Adam Speight

1

Javascript (E6) 120

เวอร์ชันซ้ำแล้วซ้ำอีก

m=d=0,n=[''];
prompt().split(/,|(\(|\))/).map(e=>e&&(e=='('?m<++d&&(n[m=d]=''):e==')'?d--:n[d]+=' '+e));
alert(m+':'+n[m])

Ungolfedและทดสอบได้

F= a=> (
    m=d=0,n=[''],
    a.split(/,|(\(|\))/)
    .map(e=>e && (e=='(' ? m < ++d && (n[m=d]='') : e==')' ? d-- : n[d]+=' '+e)),
    m+':'+n[m]
)

ทดสอบ ใน Firefox คอนโซล:

['A', '2(7(2,6(5,11)),5(9(4)))', 'A(B(C,D(E)))']
.map(x => x + ' --> ' + F(x)).join('\n')

เอาท์พุต

"A -> 0: A

2 (7 (2,6 (5,11)), 5 (9 (4))) -> 3: 5 11 4

A (B (C, D (E))) -> 3: E "

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.