0Pricing
Coding Interview Prep · Pelajaran

Diameter, Tinggi, dan Pohon Seimbang

Hitung diameter dan tinggi pohon dalam satu lintasan DFS menggunakan fungsi pembantu yang mengembalikan kedua nilai, lalu periksa apakah tinggi pohon seimbang.

Diameter, Tinggi, dan Pohon Seimbang adalah pelajaran Coding Interview Prep gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Coding Interview Prep, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Coding Interview Prep mencakup 4 pelajaran total.

Height Pohon Biner

height (atau kedalaman maksimum) pohon biner adalah panjang jalur terpanjang dari akar ke daun mana pun. Nilai ini dihitung secara rekursif: height setiap simpul adalah 1 + max(height(left), height(right)), dengan kasus dasar 0 untuk simpul kosong. Perhitungan postorder ini bersifat fundamental—height merupakan dasar untuk diameter, pemeriksaan keseimbangan, dan rotasi pohon AVL.

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

def height(root):
    if not root:
        return 0
    return 1 + max(height(root.left), height(root.right))

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
root.left.left.left = TreeNode(6)
print(height(root))  # 4

Diameter: Jalur Terpanjang

Diameter pohon biner adalah panjang jalur terpanjang antara dua simpul mana pun (jalurnya mungkin melewati akar atau tidak). Panjang jalur diukur dalam sisi. Untuk simpul mana pun, diameter yang melewati simpul tersebut sama dengan height(left) + height(right). Diameter keseluruhan adalah nilai maksimum dari nilai tersebut di semua simpul dalam pohon.

def diameter_of_binary_tree(root):
    max_diameter = [0]  # use list to allow closure mutation

    def dfs(node):
        if not node:
            return 0
        left_h = dfs(node.left)
        right_h = dfs(node.right)
        # Diameter through this node
        max_diameter[0] = max(max_diameter[0], left_h + right_h)
        return 1 + max(left_h, right_h)  # height for parent

    dfs(root)
    return max_diameter[0]

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print(diameter_of_binary_tree(root))  # 3

Satu Kali Penelusuran DFS untuk Diameter

Pendekatan naif memanggil height() di setiap simpul—O(n²) untuk pohon seimbang. Solusi optimal menghitung height dan memperbarui diameter dalam satu kali penelusuran DFS. Inti pemahamannya adalah fungsi rekursif dfs() memiliki dua tujuan sekaligus: mengembalikan height untuk induk sekaligus memperbarui diameter maksimum global sebagai efek samping. Pola postorder dengan dua tujuan ini muncul dalam banyak masalah pohon.

# O(n^2) NAIVE: recomputes height for every node
def diameter_naive(root):
    if not root:
        return 0
    through_root = height(root.left) + height(root.right)
    in_left = diameter_naive(root.left)
    in_right = diameter_naive(root.right)
    return max(through_root, in_left, in_right)

# O(n) OPTIMAL: single DFS pass (shown in previous scene)
# The naive version is O(n^2) because height() is O(n)
# and it is called for every node.
print('Naive: O(n^2) | Optimal single-pass: O(n)')

Pemeriksaan Pohon Biner Seimbang

Pohon biner disebut seimbang berdasarkan height jika height subpohon kiri dan kanan pada setiap simpul berbeda paling banyak satu. Pendekatan naif memanggil height() di setiap simpul—O(n²). Pendekatan optimal menggunakan trik satu kali penelusuran yang sama: kembalikan -1 sebagai penanda untuk 'tidak seimbang' dan teruskan nilai tersebut ke atas, dengan menghentikan proses lebih awal segera setelah ditemukan simpul yang tidak seimbang.

def is_balanced(root):
    def check(node):
        if not node:
            return 0
        left = check(node.left)
        if left == -1:
            return -1  # propagate early exit
        right = check(node.right)
        if right == -1:
            return -1
        if abs(left - right) > 1:
            return -1  # unbalanced here
        return 1 + max(left, right)  # height if balanced

    return check(root) != -1

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.left.left = TreeNode(5)  # too deep on left
print(is_balanced(root))  # False

Pola Nilai Penanda sebagai Nilai Kembalian

Mengembalikan nilai penanda (-1 untuk tidak seimbang, atau tupel khusus) adalah pola umum ketika pembantu DFS perlu menyampaikan dua jenis informasi: hasil yang dihitung dan apakah suatu batasan dilanggar. Alih-alih memunculkan pengecualian atau menggunakan penanda global, enkodekan kesalahan dalam tipe nilai kembalian. Pendekatan ini rapi, menghindari keadaan global, dan dapat dikomposisikan secara alami dengan pembantu rekursif lainnya.

# General pattern: return (is_valid, computed_value)
def balanced_height(node):
    if not node:
        return True, 0
    left_ok, left_h = balanced_height(node.left)
    if not left_ok:
        return False, 0  # short-circuit
    right_ok, right_h = balanced_height(node.right)
    if not right_ok:
        return False, 0
    balanced = abs(left_h - right_h) <= 1
    return balanced, 1 + max(left_h, right_h)

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
ok, h = balanced_height(root)
print(ok, h)  # True 2

Diameter dalam Istilah Simpul dan Sisi

Perhatikan pernyataan soal dengan saksama: LeetCode #543 mengukur diameter dalam sisi, sedangkan beberapa soal mengukurnya dalam simpul. Jika memerlukan jumlah simpul, diameter yang melewati suatu simpul adalah height(left) + height(right) + 1 (tambahkan 1 untuk simpul itu sendiri). Jika memerlukan jumlah sisi, hilangkan +1. Selalu klarifikasi hal ini dengan pewawancara sebelum menulis kode.

def diameter_in_nodes(root):
    max_path = [0]

    def dfs(node):
        if not node:
            return 0
        left_h = dfs(node.left)
        right_h = dfs(node.right)
        # Path through this node in NODE count
        nodes_through = left_h + right_h + 1
        max_path[0] = max(max_path[0], nodes_through)
        return 1 + max(left_h, right_h)

    dfs(root)
    return max_path[0]

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print(diameter_in_nodes(root))  # 4 nodes: 4-2-1-3 or 5-2-1-3

Jumlah Jalur: Jalur Akar ke Daun Mana Pun

Masalah jumlah jalur menanyakan: apakah jumlah suatu jalur dari akar ke daun sama dengan nilai target? Gunakan DFS dan kurangi nilai simpul saat ini dari target saat menuruni pohon. Pada simpul daun, periksa apakah target yang tersisa sama dengan nilai daun tersebut. Ini adalah penelusuran DFS preorder yang meneruskan jumlah yang tersisa sebagai parameter—contoh klasik rekursi dari atas ke bawah.

def has_path_sum(root, target):
    if not root:
        return False
    # Leaf node: check if we've exactly hit the target
    if not root.left and not root.right:
        return root.val == target
    remaining = target - root.val
    return (has_path_sum(root.left, remaining) or
            has_path_sum(root.right, remaining))

root = TreeNode(5)
root.left = TreeNode(4)
root.right = TreeNode(8)
root.left.left = TreeNode(11)
root.left.left.left = TreeNode(7)
root.left.left.right = TreeNode(2)
print(has_path_sum(root, 22))  # True: 5+4+11+2=22

Jumlah Jalur Maksimum (Varian Sulit)

Jumlah jalur maksimum (LeetCode #124) jauh lebih sulit: jalurnya dapat dimulai dan berakhir di simpul mana pun, bukan hanya dari akar ke daun, dan nilainya dapat negatif. Pada setiap simpul, pertimbangkan empat pilihan: hanya simpul itu sendiri, simpul + cabang kiri, simpul + cabang kanan, atau simpul + kedua cabang. Hanya tiga pilihan pertama yang dapat diteruskan ke atas menuju induk; pilihan keempat merupakan kandidat akhir untuk nilai maksimum global.

def max_path_sum(root):
    max_sum = [float('-inf')]

    def gain(node):
        if not node:
            return 0
        # Only take positive contributions
        left = max(gain(node.left), 0)
        right = max(gain(node.right), 0)
        # Best path through this node (can't go both ways upward)
        max_sum[0] = max(max_sum[0], node.val + left + right)
        # Return the best single-branch gain for parent
        return node.val + max(left, right)

    gain(root)
    return max_sum[0]

root = TreeNode(-10)
root.left = TreeNode(9)
root.right = TreeNode(20)
root.right.left = TreeNode(15)
root.right.right = TreeNode(7)
print(max_path_sum(root))  # 42: 15+20+7

Pohon AVL dan Penyeimbangan Mandiri

Pohon AVL adalah BST yang mempertahankan properti keseimbangan berdasarkan height dengan melakukan rotasi setelah operasi penyisipan dan penghapusan. Setiap simpul menyimpan faktor keseimbangan (height(kanan) - height(kiri)), yang harus tetap berada dalam {-1, 0, 1}. Ketika terjadi pelanggaran, satu rotasi atau rotasi ganda memulihkan keseimbangan dalam waktu O(1), sehingga height keseluruhan tetap O(log n) dan semua operasi dijamin O(log n).

# Balance factor = height(right) - height(left)
# AVL invariant: balance factor in {-1, 0, 1} for every node

# Four violation types and their fixes:
# LL (left-heavy left child): single right rotation
# RR (right-heavy right child): single left rotation
# LR (right-heavy left child): left rotate child, then right rotate root
# RL (left-heavy right child): right rotate child, then left rotate root

# Knowing this is enough for interviews; you rarely implement
# full AVL in an interview but must discuss the concept.
print('AVL maintains O(log n) height via rotations')

Pemeriksaan Pohon Simetris

Pohon biner bersifat simetris jika merupakan bayangan cermin dari dirinya sendiri. Periksa secara rekursif: pohon bersifat simetris jika, untuk setiap pasangan simpul yang bersesuaian di kedua sisi sumbu, nilainya sama dan subpohonnya saling mencerminkan. Definisikan pembantu is_mirror(left, right) yang memeriksa: keduanya kosong (benar), salah satunya kosong (salah), nilainya sama dan subpohon bagian dalam serta bagian luar saling mencerminkan.

def is_symmetric(root):
    def is_mirror(left, right):
        if not left and not right:
            return True
        if not left or not right:
            return False
        return (left.val == right.val and
                is_mirror(left.left, right.right) and
                is_mirror(left.right, right.left))

    return is_mirror(root.left, root.right)

sym = TreeNode(1)
sym.left = TreeNode(2)
sym.right = TreeNode(2)
sym.left.left = TreeNode(3)
sym.right.right = TreeNode(3)
print(is_symmetric(sym))  # True

nosym = TreeNode(1)
nosym.left = TreeNode(2)
nosym.right = TreeNode(2)
nosym.left.right = TreeNode(3)
print(is_symmetric(nosym))  # False

Menggabungkan Wawasan tentang Tinggi dan Diameter

Pola pascaurutan satu lintasan, yaitu ketika fungsi pembantu mengembalikan tinggi sekaligus memperbarui hasil global, dapat digunakan kembali dalam banyak masalah: diameter, jumlah jalur maksimum, pemeriksaan keseimbangan, penghitungan simpul baik, dan sebagainya. Selalu tanyakan: "informasi apa yang dibutuhkan simpul induk dari setiap simpul anak?" Itulah nilai pengembaliannya. "Perhitungan apa yang bersifat lokal pada simpul ini?" Itulah yang memperbarui jawaban global. Penguraian ini adalah keterampilan utama untuk menyelesaikan masalah pohon yang sulit.

# Reusable template for post-order dual-purpose DFS:
def tree_problem(root):
    result = [float('-inf')]  # or 0 depending on problem

    def dfs(node):
        if not node:
            return 0  # base return (height, count, etc.)
        left_val = dfs(node.left)
        right_val = dfs(node.right)
        # --- Update global result using both children ---
        candidate = left_val + right_val  # example: diameter
        result[0] = max(result[0], candidate)
        # --- Return info needed by PARENT ---
        return 1 + max(left_val, right_val)  # example: height

    dfs(root)
    return result[0]

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
print(tree_problem(root))  # diameter = 2

Pemeriksaan Singkat

Uji pemahaman Anda tentang konsep Struktur Data & Algoritma — Persiapan Wawancara Pemrograman dari pelajaran ini.

Ringkasan Pelajaran

Dalam pelajaran ini, Anda mempelajari: perhitungan tinggi menggunakan DFS pascaurutan rekursif, perhitungan diameter dalam satu lintasan O(n) menggunakan fungsi pembantu DFS dengan dua tujuan, dan pemeriksaan keseimbangan dengan penanda penghentian dini. Selanjutnya kita membahas masalah jumlah jalur dan leluhur bersama terendah.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Diameter, Tinggi, dan Pohon Seimbang” gratis?

Ya — teks lengkap “Diameter, Tinggi, dan Pohon Seimbang” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Coding Interview Prep, upgrade ke CoddyKit PRO. Kursus Coding Interview Prep mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Diameter, Tinggi, dan Pohon Seimbang”?

Hitung diameter dan tinggi pohon dalam satu lintasan DFS menggunakan fungsi pembantu yang mengembalikan kedua nilai, lalu periksa apakah tinggi pohon seimbang. Kamu berlatih Coding Interview Prep dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Coding Interview Prep?

Tidak diperlukan pengalaman sebelumnya. Coding Interview Prep di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.

Berapa lama pelajaran “Diameter, Tinggi, dan Pohon Seimbang” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Coding Interview Prep ini?

Ya. Setiap pelajaran Coding Interview Prep menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Kelas TreeNode dan BFS Berdasarkan Level
  2. DFS In-Order, Pre-Order, dan Post-Order
  3. Diameter, Tinggi, dan Pohon Seimbang
  4. Jumlah Jalur dan Leluhur Bersama Terendah
← Kembali ke Coding Interview Prep