0Pricing
Coding Interview Prep · บทเรียน

คลาส TreeNode และ BFS แบบเรียงตามระดับ

สร้างต้นไม้ทวิภาคจากอาร์เรย์ สร้าง BFS ด้วย deque เพื่อพิมพ์ทีละระดับ และแก้โจทย์ความลึกสูงสุดด้วย BFS

คลาส TreeNode และ BFS แบบเรียงตามระดับ เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

พื้นฐานของคลาส TreeNode

ต้นไม้ทวิภาคคือโครงสร้างข้อมูลแบบลำดับชั้นที่แต่ละโหนดมีลูกได้ไม่เกินสองโหนด เรียกว่า ซ้าย และ ขวา ในไพธอน เราจำลองโหนดด้วยคลาสง่าย ๆ: class TreeNode: def __init__(self, val=0, left=None, right=None) ปัญหาต้นไม้ทุกข้อในการสัมภาษณ์เริ่มต้นจากคำจำกัดความนี้ — คุณจะพบคำจำกัดความนี้ในโค้ดโครงของปัญหาต้นไม้บน LeetCode แทบทุกข้อ

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

# Build a small tree manually:
#       1
#      / \
#     2   3
#    / \
#   4   5
root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
root.left.right = TreeNode(5)
print(root.val, root.left.val, root.right.val)

การสร้างต้นไม้จากอาร์เรย์

โจทย์สัมภาษณ์มักให้อาร์เรย์ตามระดับที่ใช้แทนต้นไม้ โดย None ใช้ระบุโหนดที่หายไป เมื่อกำหนดดัชนี i ลูกด้านซ้ายจะอยู่ที่ 2i+1 และลูกด้านขวาจะอยู่ที่ 2i+2 การเขียนตัวช่วยเพื่อแปลงอาร์เรย์นี้กลับเป็น TreeNodes ที่เชื่อมโยงกันเป็นเครื่องมือที่มีประโยชน์และช่วยประหยัดเวลาในช่วงฝึกฝน

from collections import deque

def build_tree(arr):
    if not arr or arr[0] is None:
        return None
    root = TreeNode(arr[0])
    q = deque([root])
    i = 1
    while q and i < len(arr):
        node = q.popleft()
        if i < len(arr) and arr[i] is not None:
            node.left = TreeNode(arr[i])
            q.append(node.left)
        i += 1
        if i < len(arr) and arr[i] is not None:
            node.right = TreeNode(arr[i])
            q.append(node.right)
        i += 1
    return root

root = build_tree([1, 2, 3, 4, 5, None, 6])
print(root.val, root.left.val, root.right.val)

BFS คืออะไรและเหตุใดจึงใช้คิว

การค้นหาแบบกว้าง (BFS)จะเยี่ยมชมโหนดทั้งหมดที่ความลึก d ก่อนเยี่ยมชมโหนดใด ๆ ที่ความลึก d+1 การท่องผ่านทีละระดับนี้ตรงกับสิ่งที่คิว (FIFO) มอบให้พอดี: เราใส่โหนดรากเข้าคิว จากนั้นประมวลผลโหนดทีละโหนด และใส่ลูกของแต่ละโหนดเข้าคิวไปเรื่อย ๆ เมธอด collections.deque ของไพธอนมี appendleft และ popleft ที่ใช้เวลา O(1) จึงเป็นตัวเลือกที่เหมาะสมกว่าลิสต์ธรรมดา

from collections import deque

def bfs_print(root):
    if not root:
        return
    q = deque([root])
    while q:
        node = q.popleft()
        print(node.val, end=' ')
        if node.left:
            q.append(node.left)
        if node.right:
            q.append(node.right)

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
bfs_print(root)  # 1 2 3 4

BFS ตามระดับ: การจัดกลุ่มตามระดับ

รูปแบบ BFS มาตรฐานจะจัดกลุ่มโหนดตามระดับด้วยการบันทึกขนาดคิวเมื่อเริ่มต้นการวนซ้ำแต่ละรอบ ประมวลผลโหนดให้ครบตามจำนวนนั้น รวบรวมค่า แล้วจึงไปยังระดับถัดไป วิธีนี้จะสร้างรายการของรายการ ซึ่งเป็นรูปแบบผลลัพธ์ที่พบบ่อยมากในการสัมภาษณ์ สำหรับปัญหาอย่าง การท่องต้นไม้ทวิภาคตามระดับ, การท่องแบบซิกแซ็ก และ มุมมองด้านขวา

from collections import deque

def level_order(root):
    if not root:
        return []
    result = []
    q = deque([root])
    while q:
        level_size = len(q)
        level = []
        for _ in range(level_size):
            node = q.popleft()
            level.append(node.val)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        result.append(level)
    return result

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.left = TreeNode(4)
print(level_order(root))  # [[1], [2, 3], [4]]

ความลึกสูงสุดด้วย BFS

ความลึกสูงสุดของต้นไม้ทวิภาคเท่ากับจำนวนระดับในการท่องผ่านด้วย BFS เพียงนับจำนวนครั้งที่วนรอบระดับเสร็จสมบูรณ์ วิธีนี้ใช้เวลา O(n) และใช้พื้นที่ O(w) โดย w คือความกว้างสูงสุดของต้นไม้ สำหรับต้นไม้สมดุล w มีค่าเป็น O(n/2) ดังนั้นพื้นที่ในกรณีแย่ที่สุดจึงเป็น O(n)

from collections import deque

def max_depth_bfs(root):
    if not root:
        return 0
    depth = 0
    q = deque([root])
    while q:
        depth += 1
        for _ in range(len(q)):
            node = q.popleft()
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
    return depth

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

มุมมองด้านขวาของต้นไม้ทวิภาค

มุมมองด้านขวาจะคืนค่าโหนดสุดท้ายที่มองเห็นเมื่อดูต้นไม้จากด้านขวา — หรือก็คือสมาชิกตัวสุดท้ายของแต่ละระดับในการท่องผ่านด้วย BFS นี่เป็นการประยุกต์ใช้ BFS ตามระดับโดยตรง: เก็บโหนดสุดท้ายในแต่ละรอบของระดับ ความซับซ้อนด้านเวลาคือ O(n) และใช้พื้นที่ O(w) สำหรับคิว

from collections import deque

def right_side_view(root):
    if not root:
        return []
    result = []
    q = deque([root])
    while q:
        level_size = len(q)
        for i in range(level_size):
            node = q.popleft()
            if i == level_size - 1:
                result.append(node.val)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
    return result

root = TreeNode(1)
root.left = TreeNode(2)
root.right = TreeNode(3)
root.left.right = TreeNode(5)
print(right_side_view(root))  # [1, 3, 5]

การท่องต้นไม้ตามระดับแบบซิกแซ็ก

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

from collections import deque

def zigzag_level_order(root):
    if not root:
        return []
    result = []
    q = deque([root])
    left_to_right = True
    while q:
        level = []
        for _ in range(len(q)):
            node = q.popleft()
            level.append(node.val)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        result.append(level if left_to_right else level[::-1])
        left_to_right = not left_to_right
    return result

root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20)
root.right.left = TreeNode(15)
root.right.right = TreeNode(7)
print(zigzag_level_order(root))

การวิเคราะห์ความซับซ้อนด้านพื้นที่ของ BFS

BFS ใช้พื้นที่ O(w) โดยที่ w คือความกว้างสูงสุดของต้นไม้ สำหรับ ต้นไม้ทวิภาคสมบูรณ์ ที่มีโหนด n โหนด ระดับสุดท้ายจะมี (n+1)/2 โหนด ดังนั้น BFS อาจเก็บโหนดในคิวพร้อมกันได้มากถึง n/2 โหนด ทำให้ BFS ใช้พื้นที่ มากกว่า DFS (O(h)) สำหรับต้นไม้สมดุลที่กว้าง แต่ใช้พื้นที่ น้อยกว่าสำหรับต้นไม้ที่เอนลึก ซึ่งความลึกของสแตกการเรียก DFS เท่ากับ n

# Space comparison: BFS vs DFS on a complete binary tree
# n=15 nodes, height=4
# BFS max queue size = 8 (last level)
# DFS max call stack = 4 (height)

# For a skewed tree (like a linked list):
# n=1000 nodes
# BFS max queue size = 1 (always 1 node per level)
# DFS max call stack = 1000 (recursion depth -> stack overflow!)

from collections import deque

def skewed_tree(n):
    root = TreeNode(1)
    cur = root
    for i in range(2, n+1):
        cur.right = TreeNode(i)
        cur = cur.right
    return root

root = skewed_tree(10)
print('BFS on skewed tree is safe')

ค่าเฉลี่ยของแต่ละระดับในต้นไม้ทวิภาค

การคำนวณ ค่าเฉลี่ยในแต่ละระดับ เป็นการประยุกต์ใช้ BFS โดยตรงอีกรูปแบบหนึ่ง ให้รวมค่าทั้งหมดในระดับหนึ่ง หารด้วยจำนวนโหนด แล้วเพิ่มลงในรายการผลลัพธ์ โจทย์นี้ทดสอบว่าคุณสามารถคำนวณเลขคณิตภายในลูปของระดับได้ ในไพธอน 3 ให้ใช้การหารด้วยจำนวนทศนิยมเสมอ (ตัวดำเนินการ /) และจัดการกรณีต้นไม้ว่างตั้งแต่เริ่มต้น

from collections import deque

def average_of_levels(root):
    if not root:
        return []
    result = []
    q = deque([root])
    while q:
        size = len(q)
        total = 0
        for _ in range(size):
            node = q.popleft()
            total += node.val
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        result.append(total / size)
    return result

root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20)
root.right.left = TreeNode(15)
root.right.right = TreeNode(7)
print(average_of_levels(root))  # [3.0, 14.5, 11.0]

ความลึกต่ำสุดด้วย BFS

ความลึกต่ำสุด คือระยะทางจากรากไปยังโหนด ใบ ที่อยู่ใกล้ที่สุด (โหนดที่ไม่มีโหนดลูก) BFS ค้นหาค่านี้ได้อย่างมีประสิทธิภาพสูงสุด เพราะโหนดใบแรกที่พบระหว่างการท่องตามระดับจะอยู่ที่ความลึกต่ำสุดอย่างแน่นอน ให้คืนค่าความลึกปัจจุบันทันทีที่พบโหนดใบ กรณีแย่ที่สุดใช้เวลา O(n) แต่สำหรับต้นไม้สมดุลมักจะสิ้นสุดเร็วกว่านั้นมาก

from collections import deque

def min_depth(root):
    if not root:
        return 0
    q = deque([(root, 1)])
    while q:
        node, depth = q.popleft()
        # A leaf has no children
        if not node.left and not node.right:
            return depth
        if node.left:
            q.append((node.left, depth + 1))
        if node.right:
            q.append((node.right, depth + 1))
    return 0

root = TreeNode(2)
root.left = TreeNode(3)
root.left.left = TreeNode(4)
root.right = TreeNode(5)  # leaf at depth 2
print(min_depth(root))  # 2

การเชื่อมโยงโหนดพี่น้องตามระดับ

โจทย์ เติมตัวชี้ไปทางขวาถัดไป ให้คุณเชื่อมโยงแต่ละโหนดไปยังโหนดข้างขวาที่อยู่ในระดับเดียวกัน เมื่อใช้ BFS วิธีนี้ทำได้ตรงไปตรงมา โดยภายในลูปของแต่ละระดับ ให้กำหนด node.next = q[0] สำหรับทุกโหนดยกเว้นโหนดสุดท้าย นี่เป็นตัวอย่างคลาสสิกที่ BFS ทำให้เห็นวิธีแก้ได้อย่างชัดเจน ขณะที่ DFS ต้องติดตามตัวชี้ข้ามต้นไม้ย่อยอย่างระมัดระวัง

from collections import deque

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

def connect(root):
    if not root:
        return root
    q = deque([root])
    while q:
        size = len(q)
        for i in range(size):
            node = q.popleft()
            if i < size - 1:
                node.next = q[0]
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
    return root

print('BFS connect: O(n) time, O(w) space')

ตรวจสอบอย่างรวดเร็ว

ทดสอบความเข้าใจแนวคิดโครงสร้างข้อมูล & อัลกอริทึม — การเตรียมตัวสัมภาษณ์เขียนโปรแกรมจากบทเรียนนี้

บทสรุปบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้: การนิยามคลาส TreeNode และการสร้างต้นไม้จากอาร์เรย์ การใช้ BFS ตามระดับด้วยดีคิว โดยใช้เทคนิคขนาดระดับเพื่อจัดกลุ่มโหนด และ การประยุกต์ใช้ ซึ่งรวมถึงความลึกสูงสุด ความลึกต่ำสุด มุมมองด้านขวา การท่องแบบซิกแซ็ก และค่าเฉลี่ยของแต่ละระดับ บทถัดไปเราจะสำรวจลำดับการท่องแบบ DFS ด้วยการเรียกซ้ำ

คำถามที่พบบ่อย

บทเรียน “คลาส TreeNode และ BFS แบบเรียงตามระดับ” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “คลาส TreeNode และ BFS แบบเรียงตามระดับ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “คลาส TreeNode และ BFS แบบเรียงตามระดับ”

สร้างต้นไม้ทวิภาคจากอาร์เรย์ สร้าง BFS ด้วย deque เพื่อพิมพ์ทีละระดับ และแก้โจทย์ความลึกสูงสุดด้วย BFS คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “คลาส TreeNode และ BFS แบบเรียงตามระดับ” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม

ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. คลาส TreeNode และ BFS แบบเรียงตามระดับ
  2. DFS แบบลำดับกลาง ก่อน และหลัง
  3. เส้นผ่านศูนย์กลาง ความสูง และต้นไม้สมดุล
  4. ผลรวมเส้นทางและบรรพบุรุษร่วมที่ใกล้ที่สุด
← กลับไปที่ Coding Interview Prep