ต้นโหนดบนโต๊ะมิ้นต์มีเส้นทางอำพันยาวสุดพาดผ่าน และนากกายยืนมุมซ้าย

LeetCode #543 Diameter of Binary Tree: เส้นทางยาวสุดผ่านโหนดใดก็ได้

น้องกายEngineering

Diameter คือจำนวนเส้นเชื่อมในเส้นทางยาวสุดระหว่างโหนดใดๆ สองโหนด เส้นทางไม่จำเป็นต้องผ่านราก

วิธีที่ 1: ทุกโหนดคำนวณความสูงซ้าย+ขวา

ที่แต่ละโหนด candidate = สูงซ้าย + สูงขวา เก็บค่ามากสุดขณะ DFS คืนความสูงของโหนดให้พาเรนต์ เวลา O(n)

วิธีที่ 2: คำนวณความสูงแยกทุกรากย่อยแบบนาอีฟ

เรียกฟังก์ชันสูงซ้ำซ้อน O(n²) ใช้เป็น oracle บนต้นเล็ก

วิธีที่ 3: แปลงเป็นกราฟแล้ว BFS สองครั้ง

หาเส้นผ่านศูนย์กลางแบบต้นไม้ทั่วไป หนักเกินโจทย์นี้

วิธีที่ 4: DP บนต้นไม้เก็บคู่ (สูง, diameter)

คล้ายวิธี 1 แต่คืนทูเพิลชัดเจน อ่านง่ายในบางภาษา

from __future__ import annotations

import unittest


class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right


def diameter_of_binary_tree(root: TreeNode | None) -> int:
    best = 0

    def height(node: TreeNode | None) -> int:
        nonlocal best
        if node is None:
            return 0
        left = height(node.left)
        right = height(node.right)
        best = max(best, left + right)
        return 1 + max(left, right)

    height(root)
    return best


class DiameterTests(unittest.TestCase):
    def test_example(self):
        root = TreeNode(1, TreeNode(2, TreeNode(4), TreeNode(5)), TreeNode(3))
        self.assertEqual(diameter_of_binary_tree(root), 3)

    def test_single(self):
        self.assertEqual(diameter_of_binary_tree(TreeNode(1)), 0)


if __name__ == "__main__":
    unittest.main()

เลือกวิธีไหนดี

  • สัมภาษณ์ / โปรดักชันแนวต้นไม้: วิธี 1 หรือ 4
  • ตรวจคำตอบ: วิธี 2 บนอินพุตเล็ก
  • อย่าใช้วิธีกราฟยกใหญ่ถ้าไม่จำเป็น

Recap

  • diameter นับเส้น ไม่นับโหนด
  • อัปเดต best ที่ทุกโหนดจากสูงซ้าย+ขวา
  • เทสต์ต้นโหนดเดียวต้องได้ 0